Page 1 of 1

Get track+media position when playing m3u

Posted: 03 Oct 2019 20:24
by pichelo
Hi VideoLAN Forum, I hope this is the right place for my topic.
I wrote some code using libvlc that plays m3u files.
Everything worked like a charm, until I decided to introduce feature to save state when the media is stopped.
I got familiar with functions like

Code: Select all

libvlc_media_player_get_position
which correctly returns the position along the track from the m3u currently being played. This is part of the information I need to "save state on stop".
The other part is the current track being played. Is that possible at all when playing m3u?
Functions I tried:

Code: Select all

libvlc_media_list_index_of_item
always returns -1

Code: Select all

libvlc_media_list_count
always returns 1

It looks like the m3u is a single thing in the media list, still functions like

Code: Select all

libvlc_media_list_player_previous
and

Code: Select all

libvlc_media_list_player_next
work as expected.

I'm not sure whether I call the api wrong or playing m3u has some sort of limitation.
Thus writing this post to exclude the latter and maybe get some advice.

Re: Get track+media position when playing m3u

Posted: 12 Oct 2019 08:31
by sherington
Probably you need to look at subitems.

So given your current libvlc_media_t (for the m3u with one item), use libvlc_media_subitems to get the subitems (each entry in the m3u will be a subitem).

Re: Get track+media position when playing m3u

Posted: 13 Oct 2019 20:32
by pichelo
At first it didn't work, so I checked better on initialization.
My code used to create a new media list from scratch (libvlc_media_list_new), then adding the m3u media as sole item. This is why the list resulted in a single item. The strange fact is that libvlc_media_list_player_next or libvlc_media_list_player_next, worked as one would have expected. Is such behaviour expected?

The existing functionality worked the same after using libvlc_media_subitems to get the media list. This time items count returned the correct number of items, instead of 1.

Then getting the index of currently played media became a sequence of:

Code: Select all

libvlc_media_player_t *mp = libvlc_media_list_player_get_media_player libvlc_media_t *media = libvlc_media_player_get_media(mp); int curr_i = libvlc_media_list_index_of_item(media_list_from_subitems, media);[code] Thanks!

Re: Get track+media position when playing m3u

Posted: 04 Dec 2019 16:07
by pichelo
I have a new problem now. While playlist handling works like a charm, setting the position does not work anymore.
This is roughly how is done in my code (simplified C code):

Code: Select all

media = libvlc_media_new_path(_vlc, /* m3u path */); libvlc_media_parse_with_options(media, libvlc_media_parse_local | libvlc_media_parse_network, 10000); media_list = libvlc_media_subitems(media); media_list_player = libvlc_media_list_player_new(_vlc); media_player = libvlc_media_player_new(_vlc); libvlc_media_list_player_set_media_player(_media_list_player, media_player); libvlc_media_list_player_set_media_list(_media_list_player, media_list); libvlc_media_list_player_play_item_at_index(media_list_player, /* previously saved playlist item id */); libvlc_media_player_set_position(media_player, /* previously saved position (0 to 1.0) */);
Position is saved on some stop event by using libvlc_media_player_get_position, which indeed returns a proper value.
libvlc_media_list_player_play_item_at_index works as expected, but when it comes to libvlc_media_player_set_position, the call has no effect.

I tried few things, including:
- enclosing

Code: Select all

libvlc_media_player_set_position
within

Code: Select all

if (libvlc_media_player_is_seekable(media_player)) { /* set position here */ }
- loop on

Code: Select all

libvlc_media_player_is_playing
, until it returns true, then set position

Code: Select all

libvlc_media_player_set_position
used to work in the buggy code I mentioned when opening the thread.

Strange things happen is some cases, eg:
- if I put a sleep of 2 seconds before setting positions, then position is set and track is playing from there, but immediately after it moves to next track

I wonder how the semantics of

Code: Select all

libvlc_media_player_set_position
in context of media list player.

Thanks and Kind Regards

Re: Get track+media position when playing m3u

Posted: 10 Dec 2019 18:39
by mangokm40
"libvlc_media_list_player_play_item_at_index(media_list_player, /* previously saved playlist item id */);
libvlc_media_player_set_position(media_player, /* previously saved position (0 to 1.0) */);"

Might you be setiing position b4 media is playing?
Are you listening for playing event?

Re: Get track+media position when playing m3u

Posted: 13 Dec 2019 23:55
by pichelo
Hi, before I already tried something simpler like: while (!media is playing) {}, which did not work either.

Nonetheless I tried by attaching to the media playing event and this is the result:

Code: Select all

typedef struct { libvlc_event_manager_t *evt_manager; float position; } tn_set_position_user_data_t; static void _tn_media_set_position(const struct libvlc_event_t *event, void *user_data) { tn_set_position_user_data_t *position_user_data = (tn_set_position_user_data_t *) user_data; libvlc_event_detach(position_user_data->evt_manager, event->type, _tn_media_set_position, user_data); libvlc_media_player_t *media_player = (libvlc_media_player_t *) (event->p_obj); if (libvlc_media_player_is_seekable(media_player)) { syslog(LOG_INFO, "Recovering (%f)", position_user_data->position); libvlc_media_player_set_position(media_player, position_user_data->position); free(user_data); } else { syslog(LOG_WARNING, "Media is not seekable, starting from the beginning"); } libvlc_media_player_release(media_player); }
The callback is attached to to media player used by media list player by mean of:

Code: Select all

libvlc_event_manager_t *evt_manager = libvlc_media_player_event_manager(media_player); tn_set_position_user_data_t *user_data = malloc(sizeof (tn_set_position_user_data_t)); user_data->position = remember_item->media_pos;// some structure kept in memory, number is proper float between 0.0 and 1.0 retrieved by get position) user_data->evt_manager = evt_manager; libvlc_media_player_retain(media_player); // released by callback. libvlc_event_attach(evt_manager, libvlc_MediaPlayerPlaying, _tn_media_set_position, user_data);
The event gets triggered, callback is called and the log trace:

Code: Select all

syslog(LOG_INFO, "Recovering (%f)", position_user_data->position);
appears. But the media position does not change.
I tried with different media types (only using audio for this project), mp3 and ogg, but still nothing.
libvlc version is 3.0.8

Re: Get track+media position when playing m3u

Posted: 14 Dec 2019 00:19
by pichelo
After playing a bit with the callback, something unexpected happened
If I do not detach immediately the event it is called twice.
The set position call does not work the first time, but if I ignore the first event trigger (decrement a counter in user data, initialized to 1), then set position works as intended the second time!

Now I wonder why the event is triggered twice. How is that, is there a reason?
Currently I got the thing working but I feel like working around some behaviour which I did not really understand.

Re: Get track+media position when playing m3u

Posted: 14 Dec 2019 21:50
by pichelo
While investigating, something even stranger is noticed.
The media list plays even without calling either libvlc_media_list_player_play_item_at_index or libvlc_media_list_player_play.

This somehow explains the double playing event. But does not explain the unexpected behavior itself.

Is that known behavior? Can I somehow prevent auto playing of media lists?

Re: Get track+media position when playing m3u

Posted: 15 Dec 2019 20:42
by pichelo
All solved. My mistake at wiring a push button had the effect of calling libvlc_media_list_player_next, which somehow unnoticed started the track (1st event), then the expected flow arrived to "play item at index" which generated the second (proper) event.

Thanks a lot for the two answers, they were key hints to move forward.