[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