GNOME Bugzilla – Bug 321532
[cddabasesrc] Support device setting in cdda:// URI
Last modified: 2009-08-06 04:47:01 UTC
In GStreamer 0.8, if an application uses the playbin element and wishes to play an audio CD from the non-default drive, the application must handle the notify::source event to set the device on the underlying cddasrc/cdparanoia element. For 0.9, it would be nice for playbin or the underlying source element to handle this by way of the cdda:// URI. In Banshee, I am using the cdda://<track_num>#<device_node> scheme only because it is possible to pass this entire URI to the source, and it will ignore the # and anything after, which means the original URI does not need to be truncated. I then just extract <device_node> and set the device. However, for the sake of being new and clean, I think the following URI scheme makes most sense, if you think audio tracks as files or directories on the CD: cdda://<device_node>/<track_number> RhythmBox currently uses cdda://<device_node>:<track_number>. So, possible schemes: [1] cdda://8#/dev/hdc [2] cdda:///dev/hdc:8 [3] cdda:///dev/hdc/8 Ultimately, the scheme doesn't matter *too* much, so long as this support is in some level of GStreamer, and not the consuming application, but there's no reason not to make it clean and semantic, which I think goes to [3].
On second thought, I guess this belongs only at the playbin/decodebin level. If you need it on the underlying source level, you set the device/track properties respectively :)
I consider those URI schemes a gross hack, hence the different approach I chose.
Would you care to explain why you consider them such? At the playbin/decodebin level in the stack, I do not see why they are a hack. Why should the consumer have to worry about intercepting notify::source and hooking all the relevant bits up just to change the default device? Of course, the entire device node could be left out obviously, so cdda://8 plays track 8 on the default device. Another method entirely could be to just expose a device property in playbin/decodebin, but I still don't see what's wrong with a *semantic* URI.
Some of the ideas I had in mind with URI themes are this: 1. URIs are global across applications. Unlike GStreamer mime types which are local to GStreamer and do not conform to any standard, URIs must always work cross-application. They must also always conform to published RFCs. If anyone were to write a SMIL decoder using GStreamer, he should be able to just throw the URI he got in the SMIL file at GStreamer. 2. URIs should be an easy way to identify what a playback applications are currently doing. So stuff like "recent documents" or whatever can be populated with these URIs and clicking on them later makes your player play it. 3. URIs should allow a powerful way to describe input _and_ output formats desired by a GStreamer pipeline. Since plugins are supposed to be interchangeable, applications should ideally just work on URIs and not hardcode element names. Replacing cdparanoia with cddasrc or cdiosrc in Sound-Juider, Totem, Gnome-CD-player or whatever would then be a matter of installing the plugin and setting the rank. And playback applications gain access to more formats automatically if they have a "play URI" entry. To get back to the current problem: Suggestion 2 and 3 don't work, because I might actually have a device named /dev/hdc:8 or /dev/hdc/8 - or more important, someone might want to play ISOs with cdda:// Suggestion 1 limits the options for providing properties (or whatever it's called) to URIs quite a bit. And I'm not even sure if it's RFC compliant. All of them are incompatible with what MPlayer and Xine use. MPlayer uses cdda://<track-number>[/<device>] Xine uses cdda://<track-number> For me the solution MPlayer uses seems best.
Even if those URIs aren't exactly aesthetically pleasing, I wouldn't consider them a gross _hack_, more a gross convention. Connecting to notify::source is equally sucky and requires apps to keep the device string around instead of doing a simple set'n'forget. I like the MPlayer way as well.
The problem is that we add a device today and my nose tomorrow and my dog's tail the day after; it's crap. Properties are properties and can and should be accessed as such. The way to do that (notify::) is clearly documented and easy to use. Consumer arguments suck. Consumers don't know what a device node is. It's up to the application programmer, and that's you, Aaron, to do it properly. If those 5 lines of code for a notify:: signal interception are too much for you, you shouldn't be coding a music player.
Taking potential ISOs and weird device nodes (/dev/hdc/8) into account, the mplayer scheme is very reasonable. Ronald: how is being able to specify the device from which you wish to play a track on a CD in a URI any different than specifying an asboltue path to a file on a disk in a URI? It's a _path_ to the track, a map to a piece of playable media. I'm not saying remove notify::source. I'm saying the URI support should be there to _supplement_ this. If a device node is specified in a URI and notify::source sets the device node on the source, the notify::source set should then probably override the device node in the URI. Ronald: I'm also not saying notify::source is hard to use. Yes it's 5 lines of code, so what. Here's a nother angle: gst-launch playbin uri="cdda://8/dev/hdc" ... hmm... As for the consumer argument, I was not talking about an end user, I was talking about the consumer of the GStreamer framework, which happens to be the application ... using GStreamer, and I can tell you, my application does in fact happen to know what a device node is!
You want to add additional ways of doing the same things, even though: - the current way has no problems - you acknowledge that it is easy to use Why? gst-launch is feature-incomplete, has always been and will always be.
Because without URI support, it's easy to break or cause inconsistencies with other applications, unless the burden is placed _on_ the "consumer" application, which is fine, except for one little detail: all the consumer applications basically end up doing the same thing, potentially with little differences (we have thus far that I know of: cdda://<track>/<device> (mplayer), cdda://<device>:<track> (RhythmBox) cdda://<track>#<device> (Banshee). Totem probably has a scheme too, maybe it's like the RB scheme. The point is, all of these applications realize they have to handle URIs for audio CDs, so why should the underlying framework not handle them? At least then there would be a consistent convention. Say Nautilus wants to tell the default media player to play an audio CD in my non-default drive. The best way for this is... a URI, like we have for accessing all other types of media. Now the default media player has to handle that URI on its own because it's not supported in the underlying media framework. There are many media players, which would all then have essentially duplicate code to handle this. That just doesn't make sense. Why are you treating a track on a CD like it's anything different than an ogg file on a local or remote host? Doesn't that conflict with the ideals of GStreamer?
We support URIs in cdda://<num> uris. Just not the device or the kitchesink.
Saying you support cdda://<num> but not cdda://<num>[/<device>] is like saying you support file://song.ogg but not file:///absolute/path/to/song.ogg, because all ogg files should be in the home directory (the default directory). No one is saying the "kitchen sink" needs to be added in the future. Adding device node support is not opening a door for that.
I'm affraid our opinions differ there, then. A device node is not a directory. Neither are they portable, are they part of URIs on Windows or anything else.
Personally, if we end up putting the device in the URI somewhere, I'd prefer to see it as a parameter like http: cdda://8?device=/dev/hdc Done that way, we have an established standard for escaping special characters (? and &), and can provide some helper functions for elements to extract and de-escape them. This could also integrate with GstStructure, as in "gst_structure_from_uri" and "gst_structure_to_uri"
IMHO, the best format for this would be: cdda:///device#track Look at the URI format: method://host/path#fragment. method is CDDA host is localhost, so empty path is the device node to read from fragment is either nothing (the entire thing), or a track number.
While I agree that using "notify::source" isn't very hard, I would say that having support for the device name in cdda:// URIs would be extremely useful. Many GStreamer-using applications that deal with cd audio will probably want a method for uniquely representing the tracks which, because of how everything else is represented, will virtually always be URIs - because it's how other resources are represented. Having gstreamer deal with these, rather than each application writing the own (incompatible) hacks to magically change their URI into a gstreamer URI and property, would make things a lot more consistent. I dont buy the argument that being able tchange the properties is enough - after all you have elements that accept URIs like "http://host:port/path", you don't have to pass "http://path" and set the host and port seperately.
Jan: what exactly needs escaping, and what in addition to the device node would need passing in the URI to validate having to use a ...?key=val&key=val format? Anything beyond a method of absolute access to a track on a CD should be done through properties on the element. Also the device node is above the track number in depth, so it doesn't make much sense to specify the device node after the track number, even though doing so may be more compatible with GstStructure. The point is to force a standard URI format, so it should be a sensible one that follows standards. Ross: I like your method, it follows the logical standard.
What would need escaping would be & and ? characters. For cdio uri's, I don't forsee any additional parameters. My suggestion was more along the lines of providing a generic mechanism for extended URIs that we can implement in GStreamer. Other use cases? I'm not sure - there might not be any. Ross' suggestion of method://host/path#fragment has the same drawback as method://host/path:fragment - there might actually be a device named /dev/cdrom#1, it's a valid filename.
There is no problem with using the device name /dev/cdrom#1, to generate the URI the device path should be escaped: cdda:///dev/cdrom%23#6
Created attachment 68889 [details] [review] patch to make cdda:// support /dev/foo#1 syntax For our purposes at Sun, we want it so that when nautilus sends off a cdda:// URI that it works - like when you click on the CD icon that appears when the audio CD is inserted. It seems nautilus is currently sending cdda://device. So I created the attached patch that makes it work (using the cdda://device#track syntax above). I realize that this is controversial, and that people have suggested changing the format of the URL to something like "cdda://track?device=/dev/foo", but nautilus probably needs to be fixed to send this sort of URL when you click on the CD icon. I'm not sure how to make nautilus do this. So, the code probably needs more work, but people can look at the attached patch for ideas of how to do this, or use it if they just want programs like totem to stop complaining the cdda URI is not available. I found that I had to interpret the device name in both the URI handling function and when the DEVICE property is set since some programs (like totem) set the device property directly and this doesn't seem to trigger URI interpreation.
It's GnomeVFS. We can hack libgnomevfs/gnome-vfs-hal-mounts.c to include this. Two questions, though: * Supporting multiple schemes shouldn't hurt. You should at least accept old-style URIs, maybe some people read the GnomeVFS source code and now put them into a script or something * How would your scheme handle the absence of a track specification? "cdda://?device=/dev/foo"?
*** Bug 530941 has been marked as a duplicate of this bug. ***
What are the current plans for this? IMHO there's nothing wrong with accepting cdda:///dev/cdrom0#track17 kind of URIs. As Ross already said, if the device name contains a # it needs to be escaped so that's no problem either. Adding support for this will only bring advantages, we should do it! Any other oppinions?
The patch needs some work though. It doesn't free the return value of g_strsplit() and doesn't handle unescaping of the device part of the URI. And then get_uri() should return the complete URI including the track number, etc I guess. Whatever, is there still a need for this change? If not we could as well close this bug.
Created attachment 139556 [details] [review] cdda-uri.diff Updated and cleaned up patch. I'll commit this after 0.10.24 if no problems with the patch are found :)