[vlc-devel] [RFC] (libvlc) playlist changes

Pierre d'Herbemont pdherbemont at free.fr
Tue Aug 7 04:47:49 CEST 2007


Hi Filippo!

On 7 août 07, at 00:01, Filippo Carone wrote:

> while I can see clearly the problems you are addressing to the current
> playlist implementation, I'm not understanding what you really mean by
> 'tag'. This term is quite meaning-overbloated nowadays, so in order to
> be able to really catch your point, I'll make you some questions
> directly on the interface methods.

Right. We need more precision on tags. By tags we usually mean  
"unnamed tags", that is a label, or a value (which is more likely to  
be string). The problem is, unnamed tags is enough for searching, but  
not for sorting:

1) Hierarchical View
"Matrix"
	"dvd1"
		Scene1
		Scene2
	"dvd2"
		Scene1
		Scene2

- We have a nice hierarchy (current)

2) Tag View
Scene1 tags={ "Matrix", "dvd1" }
Scene2 tags={ "Matrix", "dvd1" }
Scene1 tags={ "Matrix", "dvd2" }
Scene2 tags={ "Matrix", "dvd2" }

tag_list  "Matrix", "dvd1", "dvd2"


- The problem here, is that we are mismatching types, confusing dvd  
name and dvd number. And showing such a tag list isn't ui wise.

- A solution is to implement key-value tag, which is closer to what  
is called *meta tags* and that we already implement:


3) Meta Tag View
Scene1 tags={ "dvd name"="Matrix", "dvd number"="1" }
Scene2 tags={ "dvd name"="Matrix", "dvd number"="1" }
Scene1 tags={ "dvd name"="Matrix", "dvd number"="2" }
Scene2 tags={ "dvd name"="Matrix", "dvd number"="2" }

tags = { "dvd name" = {"Matrix"}, "dvd number"={"1", "2"} }

When implementing an ui, the tags could be presented as:
| dvd name | dvd number |
     Matrix              1
     Matrix              2

(that's the column list view to browse meta tags that already exists)!

So we end up in something like:


4) (Meta+unnamed) Tags View
md1={ "song name"="Mr. Tambourine Man", "Song to listen in the  
night", "Bob collection" }
md2={ "song name"="Zion train", "Song to listen in the subway", "Bob  
collection" }

tags = { "song name" = {"Mr. Tambourine Man", "Zion train"}, "Bob  
collection", "Song to listen in the subway", "Song to listen in the  
night" }


- Usually the problem is that we could end up with many unnamed tags,  
and that the user wants to sort them.

- So what if we want to maintain some hierarchy to sort our tags?


5) (Meta+unamed hierachical) Tags View
md1={ "song name"="Mr. Tambourine Man",  "Bob collection/Song to  
listen in the night" }
md2={ "song name"="Zion train", "Bob collection/Song to listen in the  
subway" }

tags = { "song name" = {"Mr. Tambourine Man", "Zion train"}, "Bob  
collection", "Bob collection/Song to listen in the night", "Bob  
collection/Song to listen in the subway" }

(I used a '/' to denote the path for readability but implementation  
would certainly be closer to {"Bob collection","Song to listen in the  
night"}, and tags becomes a non empty array of strings. )


Hope that you have a nicer picture of the different options we have.  
4) would be the easier solution to implement and 5) would add not  
much complexity to get a hierarchy.

After all the concept doesn't bring much, but sounds good to me.

_

>> Also, jb pointed that it is hard to implement a nice playlist
>> interface from gui code. What is wanted here, is a clean interface
>> for media library, playlists, and service discovery.
>>
>> Here is one interface proposition:
>>
>> media_descriptor
>> 	_add_tag()
>> 	_tags_count()
>> 	_tag_at_index()
>> 	_event_manager()
>>
>>
>
> So a media_descriptor can be decorated by one or more tags, giving the
> ability to classify each media_descriptor in many ways and giving many
> views of the same playlist. Right?

Right. (See above.)

> The event_manager should be
> responsible for event handling, but I wouldn't expose the manager  
> itself
> as a method, but handle events with a couple of:
>
> add_<specifier>_listener()
> remove_<specifier>_listener()
>
> where <specifier> could be one of, 'tag', 'status', etc... Each  
> listener
> is fed with an event object containing all the event specific details.
> This is much what happens when handling UI events.
>
> so that each media_descriptor can have its listener (which can be the
> same object for each media_descriptor).

I don't know if you've read the new event handling code, I'll sum it up:

Event can be received with:
libvlc_event_attach( libvlc_media_instance_event_manager( p_mi ),  
libvlc_MediaInstanceStopped, mylistener_func )

void mylistener_func( libvlc_event_t * event )
{
	void * sender = event.p_obj;
	....
}

Event are send by libvlc's object threw *internal* libvlc methods:
{
	libvlc_event_t event;
	event.type = libvlc_MyCoolObjectDidSomething;
	event.my_cool_object_did_something.what_it_did = kSomething;

	libvlc_event_send( libvlc_media_instance_event_manager( p_mi ), event )
}

This give the advantages of having a quite simple code for event  
handling (see control/libvlc_internal.h and control/event.c).

The event related to an object should be available in vlc/ 
libvlc_structure.h. I think the naming conventions of the events are  
good enough to know to what class they belong to.

But I do understand that we need to keep the interface easier as we  
can for the new comer, and that I might not realize that my  
specification introduces some unneeded overhead.

So to summarize your point, the even MediaDescriptorTagAdded, should  
be handled threw:

media_descriptor
	_add_tag_added_listener( p_md, mylistener_func );
	_remove_tag_added_listener( p_md, mylistener_func );

is that right?

The drawback is the code multiplication it introduces in the libvlc  
_internal code_ (and the long function name, but that's an other  
story ;) ). But hopefully it would be simple enough, because it would  
be a simple wrapper around libvlc_event_attach.

But on the other hand, we have a better visibility of an object's  
event, as it will be defined next to its method's definition in vlc/ 
libvlc.

It sounds more than reasonable, and I really like the fact that the  
event corresponding to an object are much more advertised, but I  
still not yet sure it's worth the overhead in libvlc's internal code.  
As I may be mistaken, I'd like to have some additional third parties  
opinion on that one.

>
>> media_list
>> 	_new()
>> 	_retain()
>> 	_release()
>> 	_add_media_descriptor()
>> 	_insert_media_descriptor()
>> 	_media_descriptor_at_index()
>> 	_media_descriptor_count()
>> 	_sublist_with_tags()
>> 	_tags_count()
>> 	_tags_at_index()
>> 	_event_manager()
>>
>> media_list_player
>> 	_new_from_media_list()
>> 	_set_media_instance()
>> 	_play()
>> 	_pause()
>> 	_stop()
>> 	_event_manager()
>>
>> media_library
>> 	_default() (returns the default media library)
>> 	_media_list()
>> 	_event_manager()
>>
>>
>
> If I understand well, the library, list and list_player are  
> parented in
> this way:
>
> a media_library is the place where all the media_lists are placed; a
> media_list is a collection of media_descriptors; a  
> media_list_player is
> the actor who plays all the media_descriptors of the library it  
> belongs
> to (the _new_from_media_list()).

a media_list_player plays a media_list, that comes from where ever  
you want (not only from the media_library), that is:
- The one you created using media_list_new()
- The one from the media_library_media_list()
- The one from the media_discoverer_media_list()
- The one from media_list_sublist_with_tags()

>>
> If I understood it well, I like the overall design, but IMHO having  
> this
> level of flexibility (media_library, media_list + tags) is way too
> overkill for the 'average' application. Exposing these interfaces  
> to the
> world, since it's the aim of libvlc, could confuse developers who want
> to embed media capabilities in apps whose primary focus is not to be a
> media player with all bells'n'whistles (like videolan ;). This  
> said, my
> suggestion is to provide some smart defaults for each object of the
> chain, for example to ease development of apps which need 1 playlist
> with no hierarchies or tags. Perhaps a developer should easily create
> one media_list whose media_descriptors point to local files or remote
> uris, without having to care about all the other objects (or  
> properties)
> of the chain.

Well, if we have some clean understandable interface why not exposing  
it? But again I do agree we have to keep it simple where we can.

Anyway, the current specification allows to do, and I will ensure  
implemented code would:

p_mlist = media_list_new();

for( i = 0; i < 10; i++)
{
	asprintf( &mrl, "path/to/simpson%d.avi", i);
	p_md = media_descriptor_new( mrl );
	free( mrl );
	media_list_add( p_mlist, p_md );
	media_descriptor_release( p_md );
}

p_mp = media_player_new();
media_player_set_media_list( p_mp, p_mlist );
media_player_play( p_mp );

>
>> * Item addition/removal/changing could be easily tracked through the
>> new libvlc_event system.
>>
>> * it's not said in the proposition, but media_list_player won't run
>> in a dedicated thread
>>
>>
> Does this mean that issuing a _player_play is synchronous?

Well, the input thread start is synchronous, but the apparition of  
the vout is not (the input thread spawns it).

>> - We might loose some cool abilities we currently have (If one come
>> to your mind, please point it out)

I would add the following,

When we add a playlist file (m3u for instance), it is at first a  
media_descriptor. Once played, it is transformed to a list of new  
media_descriptor tagged with the playlist name.

Let's find how we can implement that in a nice user interface:
- We detect we are adding a m3u, and we know that it is a playlist file
- We directly parse it, and directly add the media_descriptors  
contained in the m3u (we skip first addition of the playlist  
media_descriptor).

I think we should go that way, however I am not sure it is practical  
in real world situation.

Thanks for the reading, and thanks Filippo for your answer,

Pierre.



_______________________________________________
vlc-devel mailing list
vlc-devel at videolan.org
http://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list