phonon5 and the media sources

Harald Sitter sitter at kde.org
Sat Oct 19 16:39:26 BST 2013


first off.... does anyone know how qtmm does this? I have found no way
to control a DVD using qtmm -.-

On Wed, Oct 16, 2013 at 4:25 PM, Casian Andrei <skeletk13 at gmail.com> wrote:
> Heya,
>
> For Phonon5 it looks like the "Source" class needs a complete rewrite, as
> Harald pointed out to me on IRC.
>
> Here is a quick draft API proposal for this:
>
> === Source needs to handle:
> * Local file, URL, stream
>
> * Audio CD, DVD:
> - set track
>
> * Video CD, DVD:
> - navigate menus
> - chapters, titles
> - subtitle config

I am wondering. Technically that is a SPU that might not be provided
by the source (e.g. subtitle-from-file), so right now I am actually
more inclined to say that is an effect applied to the player/output.
Though that may be confusing from an outside POV, not sure.

> - audio channels
>
> * Hardware devices:
> - set audio/video device
> - device settings
>
> === Classes:
> * GenericSource (set URL) - local files, URLs, streams

^ This would still be called Source for API clearity.
To that extend there'd also be a SourceBase class which is really only
useful for a cast base.
Source : SourceBase
AudioDiscSource : SourceBase
VideoDiscSource : SourceBase
...

For example an AbstractMediaStream source would not have a url, so
using the url source as base makes no sense IMO.

What I only realized recently though:
Subclassing has severe beauty flaws WRT how the API works.

e.g.
SourceBase Player::source();

you then need to manually figure out what source that is by casting like mad.
for example if you need to check that ::source == what you expect it
to be you need
if cast<UrlSource>(::source())
  if (cast<UrlSource>(::source()).url == m_url)
    doStuff()

so, I am not convinced we'd want to go for that. off the top of my
head here are some other approaches:

all assume one single Source class with a bunch of ctors for all
things you can use as a source.

a) Source has QList<ControlUnit *> ::controlUnits();
a control unit basically is what the MediaController was, but acting
on a Source rather than a Player.
ControlUnits again use subclassing such that you get
VideoSourceControl, DeviceSourceControl etc.
using this you still need to cast if you want to use control units,
BUT you do not if you do not want to which is quite the improvement.

b) you can decorate/attach a Source with a control unit, this is
mostly the inverse of a
this is even closer to the MC thing we had before instead of getting
units supplied by
the Source instance the developer creates their own e.g.
  VideoSourceControl control(source);
  if (control.isActive()) // false if the source does not support a VSC
    control.setChapter(0);
this completely eliminates casting and assuming an application created
a source with /dev/dvd or whatever it supposedly knows what control
unit *should* be supported.

b is actually what I prefer right now because it is what we intend to
do with effects.

> * AudioDisc (set track)
> * VideoDisc (menus, chapters, titles, subtitles, audio channels)
> * MediaDevice (set video device, set audio device, configure device)
>
> === API sketch:
> The thinking is that these multimedia sources like dvd's, hardware devices,
> etc. don't remove or drastically change features so the API shouldn't need
> to change. I'm not sure how this inheritance works with the frontend/backend
> system though...
>
> * Source (namespace? or static functions in GenericSource?) (convenience
> functions)
>  - GenericSource * Source::create(QUrl) (detects source type, creates proper
> source class)
>  - bool Source::isAudioDisc(GenericSource *) (dumb cast, gives impression of
> friendliness)
>  - bool Source::isVideoDisc(GenericSource *) (same dumb cast)
>  - bool Source::isMediaDevice(GenericSource *) (same dumb cast)

^ proof of my concern :P

> * GenericSource
>  - bool isValid()
>  - get/setUrl(QUrl)
>   a. local file: "file:///home/user/foo.avi"
>   b. some url: "http://foosite.tk/?w=abcd0000"
>   c. stream: "mms://barsite.tk:1234"
>   d. "file:///dev/video0" (url for video device?)
>   e. "file:///dev/cd" (url for disc?)
>
> * AudioDisc (derived from GenericSource)
>  - get/setTrackNumber(int)
>  - int getTrackCount
>
> * VideoDisc (like the old MediaController) (derived from GenericSource)
>  - bool canChangeMenu()
>  - QList<enum> availableMenus
>  - setCurrentMenu(enum)
>
>  - bool canChangeChapter()
>  - int chapterCount()
>  - int currentChapter()
>  - setCurrentChapter(int)
>
>  - bool canChangeAngle()
>  - int angleCount()
>  - int currentAngle()
>  - setCurrentAngle(int)
>
>  - bool canChangeTitles()
>  - bool isAutoplayTitlesEnabled()
>  - setCurrentTitle(int)
>  - setAutoplayTitlesEnabled(bool)
>  - next/previousTitle()
>
>  - bool canChangeSubititle()
>  - Subtitle currentSubtitle()
>  - QList<Subtitle> availableSubtitles()
>  - setCurrentSubtitle(Subtitle)
>  - enableSubtitleAutodetection(bool)
>  - get/setSubtitleEncoding(QString)
>  - get/setSubtitleFont(QFont)
>
>  - bool canChangeAudioChannel()
>  - QList<AudioChannel> availableAudioChannels()
>  - get/setAudioChannel
>
> * MediaDevice (derived from GenericSource)
>  - bool canSelectComplementaryDevice()
>  - setComplementaryDeviceUrl(QByteArray) (when selecting webcam + mic for av
> recording)
>  - bool canChangeVideoResolution()
>  - setVideoResolution(int x, int y)
>  - QList availableResolutions()
>  - bool canChangeAudioConfigThing()
>  - setAudioConfigThing(something)
>  - QList availableAudioConfigThings()
>
> * FancyStreamFromTheFuture (derived from ???)
>  - bool canChangeWowFeature()
>  - QList availableWowFeatureOptions()
>  - setWowFeature(Wow)
>
> === Player (class) interaction:
> - can get current source
> - can set current source
> - can get specialized source directly (or null)
>
> === Backend pov:
> * The backends must implement GenericSource
> * The backends implement AudioDisc, VideoDisc or MediaDevice if they support
> these kinds of devices

Same applies to control units, so that's cool.

> * The backends can set source validity to false if they don't like it

Actually I think with both source subclasses or units we'd want two
different properties here.

isValid() // whether the source was constructed from lead to a valid
source.... e.g. construction from invalid URL leads to an invalid
source in libphonon already

canBePlayed() // whether the source can be played by the backend, e.g.
if a MedisStream source is valid but the backend has no streamreader
it cannot be played but is still valid

^ the last property actually needs some larger considerations as
mimetype crap is going away and should be replaced with some reliable
low-resource runtime check for supportedness. so canBePlayed for
example would create a tiny pipeline and push the source in without
outputs and fast processing; if it doesn't go into error state the
file can be played.

> * The backends might be able to provide info about what kind of source is
> for a URL

Not sure what you mean.

HS



More information about the kde-multimedia mailing list