Open chrisn opened 8 years ago
Are changes needed to the specification to support this scenario?
Trying to throw some thoughts to trigger discussion here...
The scenario seems to assume that moduleB would only see tuner1 when moduleA is done with it. Another possibility would be for getTuners
to return tuner1 regardless of whether the tuner is in use. This does not solve the problem though.
If getTuners
only returns tuners that are free to use, these tuners would need to be immediately locked and hidden away from other callers as long as the app/module that called the method first does not explicitly release them, e.g. through some hypothetical unlock
method. It seems weird to lock resources by default: the app may use only one of the tuners returned for instance and requiring it to start by releasing tuners it does not need seems bad design: a spec can only constrain user agents, it cannot require Web apps to behave in a certain way, and thus should no depend on apps doing certain actions to unlock resources.
If getTuners
returns all tuners regardless of their lock state, the tuner could be locked once the app starts using it, typically when it calls setCurrentSource
. Unlocking could then be either explicit (e.g. a call to setCurrentSource(null)
would release the tuner), or implicit once there are no more references to the tuner instance. In that scenario, tuner.currentSource
and tuner.stream
must return null as long as the app has not called setCurrentSource
once (an app should not be able to see what source another app might have used). Similarly, the currentsourcechanged
event should only be triggered for source changes that occur after the initial call to setCurrentSource
.
The lock/unlock mechanism could be more explicit, for instance as done in the current draft of the WebVR API for the VRDisplay
interface with the requestPresent
and exitPresent
methods.
Now, setting the source does not necessarily mean that the app is going to use the tuner. It seems a bit heavy to lock the tuner right away. Wouldn't it be better to lock the tuner once the app actually consumes content from it, in other words when it accesses the TVMediaStream
?
That would require a change of API, somewhat similar to the discussion started in #4 "Why retrieve a list of tuners instead of just one tuner". In particular, this would suggest a model à la getUserMedia
, defined in Media Capture and Streams. In other words, this becomes possible provided the API does not expose tuners and sources as objects on which the app can operate.
In terms of WebIDL, something like:
interface TVManager {
Promise<sequence<TVChannel>> enumerateChannels();
Promise<TVMediaStream> getTunerChannel(TVChannel channel);
};
In this model, the notion of sources and tuners may still appear at the TVChannel
level, although as information, not as instances of objects that the app may control (no way to switch the tuner to a given source, no way to switch a source to another channel). From the perspective of this issue, that API would behave the same way as getUserMedia
and release the underlying resource when the TVMediaStream
instance is no longer used. The user agent would be responsible for resource management.
Obviously, among other things, I left channels scanning out of the discussion there. It could be re-introduced although not at the source level, which may be problematic (see issue #7).
In general, I prefer the model where getTuners() returns all tuners, regardless of whether they are currently available, and the resource is locked when the app starts using it (more on this below).
I also agree that an app should not be able to see what another app is using a tuner for, and so TVTuner.currentSource and TVTuner.stream should both return null until TVTuner.setCurrentSource() and TVSource.setCurrentChannel() are called respectively. I would argue that TVSource.setCurrentChannel() is probably the call that locks the resources - this would not require changes to the API.
The question then becomes what happens when a resource is in use and another request tries to claim it (whether from the same app or a different app). Should the request fail, or should it pre-empt the resources? There are valid arguments for both cases.
Steve.
I would argue that TVSource.setCurrentChannel() is probably the call that locks the resources
I think that model would allow the following scenario:
TVTuner.setCurrentSource
, succeedsTVTuner.setCurrentSource
with a different source, succeedsTVSource.setCurrentChannel
. Either the call fails because the source is no longer the current source, or the call succeeds but App 1 cannot read TVTuner.stream
since the source is no longer the current source. In both cases, App 1 did not do anything wrong, and if App 2 does not do anything with the tuner in the meantime, it can fix the problem by re-issuing a call to setCurrentSource
. It seems strange to design an API that basically encourages apps to retry in case something fails.Locking the tuner when a call to setCurrentSource
is issued would solve that problem.
I agree that an API which encourages apps to retry when something fails is not a good design choice.
This is an issue that caused much debate in other organisations I've worked with. There usually seems to end up being two schools of thought:
setCurrentChannel()
would implicitly set the source as well), it can lead to apps having resources taken away from them and having to handle that gracefully.I don't think either approach is perfect, and there are valid reasons for choosing both approaches. I'm not sure there is a "right" answer to this - it's more about choosing the one that fits best with the philosophy of the other Web APIs.
The notion of exposing underlying resources always surprises me. I would assume one of the goals of this working group would be to be aligned with video tag syntax. My organisation has taken the position that you need to know the answer to two questions:
Either tuners are irrelevant, OR all possible types of resources are relevant, in which case exposing tuner APIs is simply the start of a long trip down the rabbit hole.
The approach we take is to expose a simple play( SRC, DST ) command. The URI of the SRC & DST defines what needs to happen, the underlying system manages the allocation, yielding, locking, unlocking, etc of resources, and the application remains logically simple. Priority rules are applied [configurably] in the system (application hierarchy, most recent wins, etc) and request types themselves become the resources (i.e. LIVE, HN share, PLAYBACK, etc)
This ends up with a system completely compatibly with video tags, and something that does not start from the perspective of trying to wrap a legacy STB in W3C syntax.
Although I was saying I could see good reasons for supporting both approaches earlier in the thread, on the whole I prefer an implicit resource model, because there will almost inevitably be some implementations where that do not match the resource model you define (for a variety of very good reasons).
I can agree that your two queries are the ones we really need to expose, along with the ability to get a MediaStream object for a piece of content that can be passed to an HTML5 media element.
The complicating factor is that you may not actually know if you can play a piece of content until you've acquired some of the resources, but I think that is an asynchronous failure mode.
As raised on the mailing list here:
Are changes needed to the specification to support this scenario?