Summary: | interface for precomposed dial-strings | ||
---|---|---|---|
Product: | Telepathy | Reporter: | Simon McVittie <smcv> |
Component: | tp-spec | Assignee: | Senko Rasic <senko.rasic> |
Status: | RESOLVED FIXED | QA Contact: | Telepathy bugs list <telepathy-bugs> |
Severity: | enhancement | ||
Priority: | medium | CC: | dilinger, lassi.syrjala, olivier.crete, pekka.pessi |
Version: | unspecified | Keywords: | patch |
Hardware: | Other | ||
OS: | All | ||
URL: | http://git.collabora.co.uk/?p=user/ptlo/tp-spec-senko/.git;a=shortlog;h=refs/heads/dtmf3 | ||
Whiteboard: | |||
i915 platform: | i915 features: | ||
Bug Depends on: | |||
Bug Blocks: | 24894 |
Description
Simon McVittie
2009-11-04 05:51:25 UTC
This API is merely a shortcut for DTMF. Rather than individually calling DTMF.StartTone and DTMF.StopTone, the DialStrings interface allows one to send a batch of tones to the modem. - SendDialString(u:Stream_ID, s:DialString, u:Duration, u:Pause The DialString arg here is a string of DTMF tones; each tone is (theoretically) played for Duration ms, followed by Pause ms of silence (in actuality for something like a GSM modem that knows how to handle a DTMF string, the Pause/Duration arguments end up being ignored unless the hardware API accepts them). - CancelDialString(u:Stream_ID) - GetCurrentDialStrings(Stream_ID) => a{us}:Dial_Strings A map of Stream_ID to DialStrings currently being sent. - signal SendingDialString(u:Stream_ID, s:Dial_String) - signal StoppedDialString(u:Stream_ID, b:SucessfullySent) SuccessfullySent is false if the dialstring was cancelled. (In reply to comment #1) > This API is merely a shortcut for DTMF. Rather than individually calling > DTMF.StartTone and DTMF.StopTone, the DialStrings interface allows one to send > a batch of tones to the modem. > > - SendDialString(u:Stream_ID, s:DialString, u:Duration, u:Pause This should probably be merged into a DTMF spec. Stream_ID should be dropped (as we're planning to do for DTMF). > > The DialString arg here is a string of DTMF tones; each tone is (theoretically) > played for Duration ms, followed by Pause ms of silence (in actuality for > something like a GSM modem that knows how to handle a DTMF string, the > Pause/Duration arguments end up being ignored unless the hardware API accepts > them). > > - CancelDialString(u:Stream_ID) If SendDialString is added to DTMF, I don't see why StopTone couldn't be used in place of CancelDialString. It simplifies the interface a lot; StopTone stops any tones from playing, whether it's a single tone (started w/ StartTone), or a set of tones (started w/ SendDialString). > > - GetCurrentDialStrings(Stream_ID) => a{us}:Dial_Strings > > A map of Stream_ID to DialStrings currently being sent. I'm not convinced that this is useful. I'm also not convinced that it's not racy for a client to be using this to make any decisions about handling dialstrings. I suggest dropping it. > > - signal SendingDialString(u:Stream_ID, s:Dial_String) > > - signal StoppedDialString(u:Stream_ID, b:SucessfullySent) > > SuccessfullySent is false if the dialstring was cancelled. > Both of thee seem like important things to support. Stream_ID should be dropped. Signals should probably trigger regardless of whether SendDialString has been sent, as it is conceivable that the Channel may have the handle 1234567890p123 (where the string following the 'p' is meant to be DTMF tones that are played automatically after a call connection has been made). Is it worth sending these signals in response to StartTone/StopTone as well? We should probably reconsider how starttone/stoptone work vs dialstring, I'm not happy at having two different API calls that do more or less the same thing but in slighly different ways. Maybe we should just drop start/stop entirely and only keep SendDialString(). (In reply to comment #2) > (In reply to comment #1) > > This API is merely a shortcut for DTMF. Rather than individually calling > > DTMF.StartTone and DTMF.StopTone, the DialStrings interface allows one to send > > a batch of tones to the modem. > > > > - SendDialString(u:Stream_ID, s:DialString, u:Duration, u:Pause > > > This should probably be merged into a DTMF spec. Stream_ID should be dropped > (as we're planning to do for DTMF). The new DTMF/Dialstring interface should be moved on top of the Call.Content interface. It affects the "audio content", so it is its natural home. > > The DialString arg here is a string of DTMF tones; each tone is (theoretically) > > played for Duration ms, followed by Pause ms of silence (in actuality for > > something like a GSM modem that knows how to handle a DTMF string, the > > Pause/Duration arguments end up being ignored unless the hardware API accepts > > them). > > > > - CancelDialString(u:Stream_ID) > > If SendDialString is added to DTMF, I don't see why StopTone couldn't be used > in place of CancelDialString. It simplifies the interface a lot; StopTone > stops any tones from playing, whether it's a single tone (started w/ > StartTone), or a set of tones (started w/ SendDialString). That won't work. Currently you can call start(1)/stop/start(2)/stop without pause and it will be the same as sending the "12" dialstring. That said, I don't think anyone actually uses that method, so I'd just drop it. > > - GetCurrentDialStrings(Stream_ID) => a{us}:Dial_Strings > > > > A map of Stream_ID to DialStrings currently being sent. > > I'm not convinced that this is useful. I'm also not convinced that it's not > racy for a client to be using this to make any decisions about handling > dialstrings. I suggest dropping it. I agree, drop it. I don't think any client actually uses it. How about something like the following? http://git.collabora.co.uk/?p=user/dilinger/telepathy-spec;a=shortlog;h=refs/heads/dtmf (In reply to comment #4) > How about something like the following? > > http://git.collabora.co.uk/?p=user/dilinger/telepathy-spec;a=shortlog;h=refs/heads/dtmf ++ + <tp:added version="0.19.0">(draft 1)</tp:added> 0.19.UNRELEASED please; whoever does the 0.19.1 release will correct that to 0.19.1, assuming this branch isn't delayed. (Rationale: this stops branches that don't make it into the target release from having incorrect information.) + <tp:docstring>The number of milliseconds to play each tone. May + be ignored.</tp:docstring> "The connection manager MAY ignore this parameter if it cannot alter the length of tones", please; likewise for Pause. + The supplied Tones string, Duration, or Pause was invalid. What does it mean to have an invalid Duration or Pause? I wonder whether we should say that the Duration and Pause SHOULD automatically be clamped within reasonable limits by the CM (so a Duration of 100 seconds ends up as the CM's hard-coded maximum, 2 seconds or whatever). Perhaps there should also be a reserved value (maybe 0xFFFFFFFF, the maximum unsigned int32) that means "use a default duration and pause for this protocol"? Or is it, in practice, either fixed or the UI's choice? Missing things here which the old interface had: * How do you send tones "live" via a dial-pad, e.g. for "for sales and support, press 3"? I infer that the answer is SendTones("3", x, x) for suitable x, or possibly SendTones("3", x, x) for very large x on press and CancelTones() on release; this should be documented explicitly. * If you send "overlapping" tones (call SendTones a second time while tones are still playing), what happens? I suspect the only sensible answer is to say they're queued up, but this should be documented explicitly. Is this interface suitable for XMPP and SIP as well as GSM? I'd like to see an opinion from whoever designed the old DTMF interface (assuming it wasn't Olivier all along :-) (In reply to comment #6) > * How do you send tones "live" via a dial-pad, e.g. for "for sales and support, > press 3"? I infer that the answer is SendTones("3", x, x) for suitable x, or > possibly SendTones("3", x, x) for very large x on press and CancelTones() on > release; this should be documented explicitly. Maybe I can propose duration=0 means "automatic" and duration="very long" (or -1) means "needs to be manually stopped or will last a very long time". > * If you send "overlapping" tones (call SendTones a second time while tones are > still playing), what happens? I suspect the only sensible answer is to say > they're queued up, but this should be documented explicitly. The DTMF GStreamer elements will queue them up and enforce a minimum duration and pause that we've found to make most IVRs happy. The spec should probably say something similar > Is this interface suitable for XMPP and SIP as well as GSM? I'd like to see an > opinion from whoever designed the old DTMF interface (assuming it wasn't > Olivier all along :-) Old DTMF was Rob and me, and it seems fine to me. (In reply to comment #7) > (In reply to comment #6) > > * How do you send tones "live" via a dial-pad, e.g. for "for sales and support, > > press 3"? I infer that the answer is SendTones("3", x, x) for suitable x, or > > possibly SendTones("3", x, x) for very large x on press and CancelTones() on > > release; this should be documented explicitly. > > Maybe I can propose duration=0 means "automatic" and duration="very long" (or > -1) means "needs to be manually stopped or will last a very long time". > I like this. I would even go so far as to say that, if duration=0 means "automatic", CMs should actually honor non-automatic values. That is, if the client specifies duration=50 and the CM cannot play the tone for 50ms (due to hardware/network requirements), SendTones should return an error. Given that, CMs should also be required to specify a default duration/pause. (Note that another option is to have another argument which takes an enum { DURATION_AUTOMATIC, DURATION_SPECIFIED, DURATION_FOREVER }.) > > * If you send "overlapping" tones (call SendTones a second time while tones are > > still playing), what happens? I suspect the only sensible answer is to say > > they're queued up, but this should be documented explicitly. > > The DTMF GStreamer elements will queue them up and enforce a minimum duration > and pause that we've found to make most IVRs happy. The spec should probably > say something similar Not Error.NotAvailable or Error.ServiceBusy? I've updated http://git.collabora.co.uk/?p=user/dilinger/telepathy-spec;a=shortlog;h=refs/heads/dtmf to address Simon's concerns. Note that this adds a ServiceBusy error for the case of overlapping SendTones calls. I've also created a separate spec that keeps StartTone, and implements MultipleTones (without Pause/Duration arguments; it is assumed that the CM will define those): http://git.collabora.co.uk/?p=user/dilinger/telepathy-spec;a=log;h=refs/heads/dtmf2 I'm partial to the dtmf2 branch, myself. The DTMF2 client-side interface seems good to me. I wonder how the cm->tp-fs interface should look like. A spec cabal of smcv, cassidy, sjoerd and myself seemed generally keener on the dtmf2 branch too. Recurring question: do we really care which content the DTMF tones are going to be sent over? How is a UI ever going to know which one the user meant? Can we just make it an interface on the channel with no stream IDs, and say it's up to the CM? If we did that, then we could in principle use the same interface on Call, and just say that on call the stream IDs are ignored... Saves having two interfaces, at the cost of a bit of cruft. Relatedly, we could glue MultipleTones() onto this existing interface in any case. Alternatively, can we get rid of start/stop entirely in favour of SendMultiple? Do we want to support people playing happy birthday to their friends? smcv suggests not; wjt suggests that we do, and given that that's the API we currently have implemented in a bunch of places... Regarding overlapping calls: first, we could say that only the channel's handler should be using this interface. Then we can say that calling StartTone(3), StopTone(), StartTone(4), StopTone() is the same as if you omit the first StopTone()? We don't support sending >1 tone at the same time, so the CM should queue them if it hasn't finished playing the current tone. What's the use case for SendingTones? It's racy for the UI to change its behaviour based on it, like muting the microphone. But it's probably fine for informational purposes. (In reply to comment #11) > Recurring question: do we really care which content the DTMF tones are going to > be sent over? How is a UI ever going to know which one the user meant? Can we > just make it an interface on the channel with no stream IDs, and say it's up to > the CM? > > If we did that, then we could in principle use the same interface on Call, and > just say that on call the stream IDs are ignored... Saves having two > interfaces, at the cost of a bit of cruft. Relatedly, we could glue > MultipleTones() onto this existing interface in any case. Why would you ever want to put it on the Channel instead of on the Content? Can you have a useful Call channel with no content? > Regarding overlapping calls: first, we could say that only the channel's > handler should be using this interface. Then we can say that calling > StartTone(3), StopTone(), StartTone(4), StopTone() is the same as if you omit > the first StopTone()? We don't support sending >1 tone at the same time, so the > CM should queue them if it hasn't finished playing the current tone. Imho, the CM should just forward the tones to the streaming implementation which will decide when to play them. > What's the use case for SendingTones? It's racy for the UI to change its > behaviour based on it, like muting the microphone. But it's probably fine for > informational purposes. I think the use case is to display a banner "sending DTMF" (like Fremantle does) (In reply to comment #11) > A spec cabal of smcv, cassidy, sjoerd and myself seemed generally keener on the > dtmf2 branch too. > > Recurring question: do we really care which content the DTMF tones are going to > be sent over? How is a UI ever going to know which one the user meant? Can we > just make it an interface on the channel with no stream IDs, and say it's up to > the CM? I'd prefer it to be an interface on the channel interface, but I don't feel strongly about it one way or the other. > > If we did that, then we could in principle use the same interface on Call, and > just say that on call the stream IDs are ignored... Saves having two > interfaces, at the cost of a bit of cruft. Relatedly, we could glue > MultipleTones() onto this existing interface in any case. > > Alternatively, can we get rid of start/stop entirely in favour of SendMultiple? > Do we want to support people playing happy birthday to their friends? smcv > suggests not; wjt suggests that we do, and given that that's the API we > currently have implemented in a bunch of places... > I think it's important from a UI perspective to hear tones when one holds down a key. This is helpful when navigating an automated phone system ("press 1 to hear this in english. pará español, empuje el número 2, ..."). When one eventually gets frustrated at the phone menu and starts mashing 0 repeatedly, one would not want to deprive the user of the satisfaction of hearing those angry tones. > Regarding overlapping calls: first, we could say that only the channel's > handler should be using this interface. Then we can say that calling > StartTone(3), StopTone(), StartTone(4), StopTone() is the same as if you omit > the first StopTone()? We don't support sending >1 tone at the same time, so the > CM should queue them if it hasn't finished playing the current tone. > I don't have a problem w/ a StartTone call implicitly ending any prior playing tones, I just wouldn't want to see the kind of situation where someone mashes buttons on their phone (accidentally or not), and the CM then proceeds to spend the next 20s playing queued-up tones. MultipleTones() is meant to automatically take care of timings; StartTone/StopTone is meant to happen immediately. What happens when MultipleTones is running, and StartTone(3) is called? Should that quietly truncate the currently playing tone string? > What's the use case for SendingTones? It's racy for the UI to change its > behaviour based on it, like muting the microphone. But it's probably fine for > informational purposes. > I'm imagining things like a UI number display. You're at a phone menu, dialing your fedex tracking number (followed by the #). StartTone(5), StopTone(), StartTone(4), StopTone, StartTone(3), etc... How does the UI know whether the tone actually ended up being played? SendingTones informs you that the number has been played, and therefore the UI should display the played number. For newly placed calls like '3214p123', SendingTones is an indicator to the UI that the call's not quite ready for user input; StoppedTones tells the UI that the call is ready for the user to mangle. I don't think stuff like muting need be handled at the UI level; the CM is presumably capable of muting any audio while playing tones (if necessary). (In reply to comment #13) > I'd prefer it to be an interface on the channel interface, but I don't feel > strongly about it one way or the other. I think my position on this is: from a theoretical stand-point it should be on the content, and as Olivier says UIs have to deal with contents anyway. But in practice I doubt any UI that supports a dial-pad will support >1 audio content so it probably makes zero practical difference. > I think it's important from a UI perspective to hear tones when one holds down > a key. This is helpful when navigating an automated phone system ("press 1 to > hear this in english. pará español, empuje el número 2, ..."). When one > eventually gets frustrated at the phone menu and starts mashing 0 repeatedly, > one would not want to deprive the user of the satisfaction of hearing those > angry tones. :D > What happens when MultipleTones is running, and StartTone(3) is called? Should > that quietly truncate the currently playing tone string? > > > > What's the use case for SendingTones? It's racy for the UI to change its > > behaviour based on it, like muting the microphone. But it's probably fine for > > informational purposes. > > > > I'm imagining things like a UI number display. You're at a phone menu, dialing > your fedex tracking number (followed by the #). StartTone(5), StopTone(), > StartTone(4), StopTone, StartTone(3), etc... How does the UI know whether the > tone actually ended up being played? SendingTones informs you that the number > has been played, and therefore the UI should display the played number. > > For newly placed calls like '3214p123', SendingTones is an indicator to the UI > that the call's not quite ready for user input; StoppedTones tells the UI that > the call is ready for the user to mangle. I don't think stuff like muting need > be handled at the UI level; the CM is presumably capable of muting any audio > while playing tones (if necessary). Sounds like the UI should wait until any MultipleTones() in progress have finished by waiting for StoppedTones before letting the user mash buttons? (In reply to comment #14) > (In reply to comment #13) > > > What's the use case for SendingTones? It's racy for the UI to change its > > > behaviour based on it, like muting the microphone. But it's probably fine for > > > informational purposes. > > > > > > > I'm imagining things like a UI number display. You're at a phone menu, dialing > > your fedex tracking number (followed by the #). StartTone(5), StopTone(), > > StartTone(4), StopTone, StartTone(3), etc... How does the UI know whether the > > tone actually ended up being played? SendingTones informs you that the number > > has been played, and therefore the UI should display the played number. > > > > For newly placed calls like '3214p123', SendingTones is an indicator to the UI > > that the call's not quite ready for user input; StoppedTones tells the UI that > > the call is ready for the user to mangle. I don't think stuff like muting need > > be handled at the UI level; the CM is presumably capable of muting any audio > > while playing tones (if necessary). > > Sounds like the UI should wait until any MultipleTones() in progress have > finished by waiting for StoppedTones before letting the user mash buttons? > Exactly. And if the UI just sends them straight through, ServiceBusy errors are returned until MultipleTones() is done. Here's a summary and my suggestions, from a POV of someone first reading through this yesterday: 1. Using existing Channel.DTMF interface vs creating Call.Content.DTMF Although using Call.Content.DTMF looks cleaner, the fact is that if we do that, we'll end up with two basically same interfaces, except one has a few extra methods/signals. Otherwhere in the spec, we only have this if the new/expanded interface has a lot more features (and is more complicated to use and is not always needed for simple clients), e.g. Text vs Messages. In this case, however, we'd just be duplicating almost-but-not-quite the same functionality. Unless we plan to deprecate Channel.DTMF quickly, I'm more for reusing and extending the existing one. 2. Do we care about calls with >1 audio streams? IMHO we don't. If there are multiple audio streams, I guess the natural thing to do is send tones on all of them (that support it). If we can't make a realistic use case where we'd want to send tones only to a subset (reading the bug comments I didn't see any, maybe the spec cabal discussed that), IMHO we better not try to be too much future-ready. Btw since we have to keep the Stream_ID parameter to ensure backwards compatibility (but ignore it), we can, if we think that's a good idea, repurpose it again (e.g. an invalid ID meaning send to all, a specific ID meaning send to only that stream). 3. SendMultiple/StartTone/StopTone and the signals It makes sense to treat SendMultiple() for fire&forget use cases, and still retain StartTone/StopTone for the interactive dialpad use (if we're using the existing interface, they're there already with the same semantics). As we don't support queueing or overlaping tones, we can mandate that SendMultiple/StartTone only be called if there are no tones currently being sent (and since explicit is better than implicit - require that any previous playback is stopped before new StartTone call), and that StopTone stops any sending. Relatedly - are we certain we can cancel queued-up tones on all protocols? If no, StopTone shouldn't say "immediately stops tone sending" and should instead ys "immediately stops tone sending if StartTone is used; for SendMultiple, attempts to cancel the send; the client shouldn't assume the tones are stopped before StoppedTones is emitted". I've created another branch (dtmf3 in my repo) implementing the above things: http://git.collabora.co.uk/?p=user/ptlo/tp-spec-senko/.git;a=shortlog;h=refs/heads/dtmf3 I've taken a definitive stance on how to define this, hopefully we can say "yes" or "no" to specific points, polish this (or dtmf2) according to that, and badger this into submission^Wmergeable state. (In reply to comment #16) > I'm more for reusing and extending the existing one. Will, Sjoerd and I agree - keep it as a Channel interface. > 2. Do we care about calls with >1 audio streams? > > IMHO we don't. We agree. > As we don't support queueing or overlaping tones, we can mandate that > SendMultiple/StartTone only be called if there are no tones currently being > sent (and since explicit is better than implicit - require that any previous > playback is stopped before new StartTone call), and that StopTone stops any > sending. We agree. > Relatedly - are we certain we can cancel queued-up tones on all protocols? If > no, StopTone shouldn't say "immediately stops tone sending" and should instead > ys "immediately stops tone sending if StartTone is used; for SendMultiple, > attempts to cancel the send; the client shouldn't assume the tones are stopped > before StoppedTones is emitted" We agree. Issue: suppose you have the phone number 12345p987 in your address book (i.e. dial 12345, wait, send 987 as DTMF to select extension 987). Two routes we could go here: * Require the address book to know about phones, and make a request with {TargetID: "12345", InitialDTMF: "987" } * Make a request with { TargetID: "12345p987" } and have the CM interpret it The latter needs changes to TpBaseConnection, to have it not delete the requested (non-normalized) TargetID from the request as it currently does. (Currently, TargetID is removed, and replaced with a TargetHandle.) We can do that, though. In either case, 12345p987 should normalize to 12345, and hence the NewChannels signal (and the channel's immutable properties) should contain { TargetID: "12345", InitialDTMF: "987" }. Spec cabal consensus is to have telephonic CMs support both of these modes. API needing to be added is: * InitialDTMF (immutable and requestable) (could be InitialTones or something - bikeshed) * some way to know (state-recovery) that you're already sending, so you can wait to not be sending before making the dial pad widget sensitive - we propose a property CurrentlySendingTones: b with change notification via SendingTones, StoppedTones. We should ask the telephonic CM implementors who's responsible for playing feedback to the user on HardwareStreaming CMs. People who know about Farsight need to ponder how we get feedback played on HardwareStreaming=FALSE CMs. There are two cases here: * the DTMF is sent in the signalling: the CM needs to poke the streaming implementation and say "play audible feedback for 'one two hash star' but don't send it"; * the DTMF is sent in-band in the RTP: the CM needs to poke the streaming implementation and say "emit 'one two hash star' in your RTP and also play audible feedback for it". (In reply to comment #17) > (In reply to comment #16) > > I'm more for reusing and extending the existing one. > > Will, Sjoerd and I agree - keep it as a Channel interface. > > > 2. Do we care about calls with >1 audio streams? > > > > IMHO we don't. > > We agree. > > > As we don't support queueing or overlaping tones, we can mandate that > > SendMultiple/StartTone only be called if there are no tones currently being > > sent (and since explicit is better than implicit - require that any previous > > playback is stopped before new StartTone call), and that StopTone stops any > > sending. > > We agree. > > > Relatedly - are we certain we can cancel queued-up tones on all protocols? If > > no, StopTone shouldn't say "immediately stops tone sending" and should instead > > ys "immediately stops tone sending if StartTone is used; for SendMultiple, > > attempts to cancel the send; the client shouldn't assume the tones are stopped > > before StoppedTones is emitted" > > We agree. Farsight currently always queues tones (we enforce minimum lenghts and intertones delays) and doesn't have a concept of Stop NOW (stop is just a message thats also queued). > People who know about Farsight need to ponder how we get feedback played on > HardwareStreaming=FALSE CMs. There are two cases here: > > * the DTMF is sent in the signalling: the CM needs to poke the streaming > implementation and say "play audible feedback for 'one two hash star' but don't > send it"; > > * the DTMF is sent in-band in the RTP: the CM needs to poke the streaming > implementation and say "emit 'one two hash star' in your RTP and also play > audible feedback for it". Feedback is not a farsight issue. That said, with the dtmfsrc element, it is trivial to produce DTMF sounds with a simple GStreamer pipeline like "dtmfsrc ! autoaudiosink" then then just send events to it. (In reply to comment #17) > API needing to be added is: > > * InitialDTMF (immutable and requestable) (could be InitialTones or something - > bikeshed) Since the rest of the API is *Tones, I'd rather go with InitialTones. > * some way to know (state-recovery) that you're already sending, so you can > wait to not be sending before making the dial pad widget sensitive - we propose > a property CurrentlySendingTones: b with change notification via SendingTones, > StoppedTones. Updated my branch with both additions, but would want to find about the feedback issue before I resubmit for review. While we're bikeshedding, maybe we can collapse SendingTones/StoppedTones into one SendingTones(sending:b) signal, to parallel the new propery. > We should ask the telephonic CM implementors who's responsible for playing > feedback to the user on HardwareStreaming CMs. Pekka, could you please comment on this? (In reply to comment #18) > Feedback is not a farsight issue. So, for HardwareStreaming=FALSE at least, the client program is responsible for DTMF feedback (if it wants the user to hear it). These have been in the spec since 0.19.6. |
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.