mirror of
https://code.videolan.org/videolan/vlc
synced 2024-10-03 01:31:53 +02:00
DBus control: add more TrackList signals
Implements the following signals for the org.mpris.MediaPlayer2.TrackList interface: - TrackAdded: a track was inserted to the list - TrackRemoved: a track was removed from the list
This commit is contained in:
parent
b2a5d6cc75
commit
c839ffd9a6
@ -89,6 +89,10 @@ static const DBusObjectPathVTable dbus_mpris_vtable = {
|
||||
typedef struct
|
||||
{
|
||||
int signal;
|
||||
union {
|
||||
tracklist_append_event_t *items_appended;
|
||||
tracklist_remove_event_t *items_removed;
|
||||
};
|
||||
} callback_info_t;
|
||||
|
||||
enum
|
||||
@ -639,6 +643,14 @@ static void ProcessEvents( intf_thread_t *p_intf,
|
||||
vlc_dictionary_init( &tracklist_properties, 0 );
|
||||
vlc_dictionary_init( &root_properties, 0 );
|
||||
|
||||
// In case multiple *_ITEM_APPEND or *_ITEM_DELETED events appear on the
|
||||
// list, the elements in their respective map values will be linked in
|
||||
// order.
|
||||
// We keep the tail of the list in order to append the elements to the end
|
||||
// of each list.
|
||||
tracklist_append_event_t *last_append = NULL;
|
||||
tracklist_remove_event_t *last_remove = NULL;
|
||||
|
||||
for( int i = 0; i < i_events; i++ )
|
||||
{
|
||||
switch( p_events[i]->signal )
|
||||
@ -653,9 +665,27 @@ static void ProcessEvents( intf_thread_t *p_intf,
|
||||
vlc_dictionary_insert( &player_properties, "Metadata", NULL );
|
||||
break;
|
||||
case SIGNAL_PLAYLIST_ITEM_APPEND:
|
||||
if( !last_append ) {
|
||||
assert (!vlc_dictionary_has_key( &tracklist_properties, "TrackAdded" ) );
|
||||
vlc_dictionary_insert( &tracklist_properties, "TrackAdded", p_events[i]->items_appended );
|
||||
|
||||
last_append = p_events[i]->items_appended;
|
||||
} else {
|
||||
last_append->change_ev.next = &p_events[i]->items_appended->change_ev;
|
||||
last_append = p_events[i]->items_appended;
|
||||
}
|
||||
ProcessPlaylistChanged( p_intf, &player_properties, &tracklist_properties );
|
||||
break;
|
||||
case SIGNAL_PLAYLIST_ITEM_DELETED:
|
||||
if( !last_remove ) {
|
||||
assert (!vlc_dictionary_has_key( &tracklist_properties, "TrackRemoved" ) );
|
||||
vlc_dictionary_insert( &tracklist_properties, "TrackRemoved", p_events[i]->items_removed );
|
||||
|
||||
last_remove = p_events[i]->items_removed;
|
||||
} else {
|
||||
last_remove->change_ev.next = &p_events[i]->items_removed->change_ev;
|
||||
last_remove = p_events[i]->items_removed;
|
||||
}
|
||||
ProcessPlaylistChanged( p_intf, &player_properties, &tracklist_properties );
|
||||
break;
|
||||
case SIGNAL_VOLUME_MUTED:
|
||||
@ -1018,18 +1048,22 @@ playlist_on_items_added(vlc_playlist_t *playlist, size_t index,
|
||||
vlc_playlist_item_t *const items[], size_t count,
|
||||
void *data)
|
||||
{
|
||||
tracklist_append_event_t *append_event = tracklist_append_event_create(index, items, count);
|
||||
add_event_signal(data,
|
||||
&(callback_info_t){ .signal = SIGNAL_PLAYLIST_ITEM_APPEND });
|
||||
(void) playlist; (void) index; (void) items; (void) count;
|
||||
&(callback_info_t){ .signal = SIGNAL_PLAYLIST_ITEM_APPEND,
|
||||
.items_appended = append_event });
|
||||
(void) playlist;
|
||||
}
|
||||
|
||||
static void
|
||||
playlist_on_items_removed(vlc_playlist_t *playlist,
|
||||
size_t index, size_t count, void *data)
|
||||
{
|
||||
tracklist_remove_event_t *remove_event = tracklist_remove_event_create(index, count);
|
||||
add_event_signal(data,
|
||||
&(callback_info_t){ .signal = SIGNAL_PLAYLIST_ITEM_DELETED });
|
||||
(void) playlist; (void) index; (void) count;
|
||||
&(callback_info_t){ .signal = SIGNAL_PLAYLIST_ITEM_DELETED,
|
||||
.items_removed = remove_event });
|
||||
(void) playlist;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -36,6 +36,42 @@
|
||||
#include "dbus_tracklist.h"
|
||||
#include "dbus_common.h"
|
||||
|
||||
|
||||
tracklist_append_event_t *tracklist_append_event_create(size_t index, vlc_playlist_item_t *const items[], size_t count) {
|
||||
tracklist_append_event_t* result = malloc(sizeof(tracklist_append_event_t) + sizeof(vlc_playlist_item_t *[count]));
|
||||
if (!result)
|
||||
return result;
|
||||
|
||||
*result = (tracklist_append_event_t) { .change_ev = { .index = index, .count = count } };
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
result->items[i] = items[i];
|
||||
vlc_playlist_item_Hold(items[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
tracklist_remove_event_t *tracklist_remove_event_create(size_t index, size_t count) {
|
||||
tracklist_remove_event_t* result = malloc(sizeof(tracklist_remove_event_t));
|
||||
if (!result)
|
||||
return result;
|
||||
|
||||
*result = (tracklist_remove_event_t) { .change_ev = { .index = index, .count = count } };
|
||||
return result;
|
||||
}
|
||||
|
||||
void tracklist_append_event_destroy(tracklist_append_event_t *event) {
|
||||
if (!event)
|
||||
return;
|
||||
for (size_t i = 0; i < event->change_ev.count; ++i) {
|
||||
vlc_playlist_item_Release(event->items[i]);
|
||||
}
|
||||
free(event);
|
||||
}
|
||||
|
||||
void tracklist_remove_event_destroy(tracklist_remove_event_t *event) {
|
||||
free(event);
|
||||
}
|
||||
|
||||
DBUS_METHOD( AddTrack )
|
||||
{
|
||||
REPLY_INIT;
|
||||
@ -242,11 +278,29 @@ invalid_track_id:
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
static int MarshalTrack( DBusMessageIter *iter, size_t index )
|
||||
{
|
||||
char *psz_track_id = NULL;
|
||||
int ret = VLC_SUCCESS;
|
||||
|
||||
if (asprintf(&psz_track_id, MPRIS_TRACKID_FORMAT, index) == -1)
|
||||
ret = VLC_ENOMEM;
|
||||
|
||||
if (ret == VLC_SUCCESS &&
|
||||
!dbus_message_iter_append_basic( iter,
|
||||
DBUS_TYPE_OBJECT_PATH,
|
||||
&psz_track_id ) )
|
||||
{
|
||||
ret = VLC_ENOMEM;
|
||||
}
|
||||
free( psz_track_id );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
MarshalTracks( intf_thread_t *p_intf, DBusMessageIter *container )
|
||||
{
|
||||
DBusMessageIter tracks;
|
||||
char *psz_track_id = NULL;
|
||||
vlc_playlist_t *playlist = p_intf->p_sys->playlist;
|
||||
|
||||
dbus_message_iter_open_container( container, DBUS_TYPE_ARRAY, "o",
|
||||
@ -257,16 +311,12 @@ MarshalTracks( intf_thread_t *p_intf, DBusMessageIter *container )
|
||||
vlc_playlist_Unlock(playlist);
|
||||
for (size_t i = 0; i < pl_size; i++)
|
||||
{
|
||||
if (asprintf(&psz_track_id, MPRIS_TRACKID_FORMAT, i) == -1 ||
|
||||
!dbus_message_iter_append_basic( &tracks,
|
||||
DBUS_TYPE_OBJECT_PATH,
|
||||
&psz_track_id ) )
|
||||
int err = MarshalTrack( &tracks, i );
|
||||
if (err != VLC_SUCCESS)
|
||||
{
|
||||
dbus_message_iter_abandon_container( container, &tracks );
|
||||
return VLC_ENOMEM;
|
||||
return err;
|
||||
}
|
||||
|
||||
free( psz_track_id );
|
||||
}
|
||||
|
||||
if( !dbus_message_iter_close_container( container, &tracks ) )
|
||||
@ -467,8 +517,64 @@ PropertiesChangedSignal( intf_thread_t *p_intf,
|
||||
}
|
||||
|
||||
/**
|
||||
* TrackListPropertiesChangedEmit: Emits the
|
||||
* org.freedesktop.DBus.Properties.PropertiesChanged signal
|
||||
* TrackAddedSignal: synthetizes and sends the
|
||||
* org.mpris.MediaPlayer2.TrackList.TrackAdded signal
|
||||
*/
|
||||
static DBusHandlerResult
|
||||
TrackAddedSignal( intf_thread_t *p_intf,
|
||||
size_t index,
|
||||
vlc_playlist_item_t *item )
|
||||
{
|
||||
DBusConnection *p_conn = p_intf->p_sys->p_conn;
|
||||
DBusMessageIter meta;
|
||||
|
||||
SIGNAL_INIT( "MediaPlayer2.TrackList",
|
||||
DBUS_MPRIS_OBJECT_PATH,
|
||||
"TrackAdded" );
|
||||
|
||||
OUT_ARGUMENTS;
|
||||
|
||||
if( unlikely(!dbus_message_iter_open_container( &args,
|
||||
DBUS_TYPE_ARRAY, "a{sv}",
|
||||
&meta )) )
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
|
||||
GetInputMeta(index, item, &meta);
|
||||
|
||||
if( unlikely(!dbus_message_iter_close_container( &args,
|
||||
&meta )) )
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
|
||||
if ( MarshalTrack( &args, index ) != VLC_SUCCESS )
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
|
||||
SIGNAL_SEND;
|
||||
}
|
||||
|
||||
/**
|
||||
* TrackRemovedSignal: synthetizes and sends the
|
||||
* org.mpris.MediaPlayer2.TrackList.TrackRemoved signal
|
||||
*/
|
||||
static DBusHandlerResult
|
||||
TrackRemovedSignal( intf_thread_t *p_intf, size_t index )
|
||||
{
|
||||
DBusConnection *p_conn = p_intf->p_sys->p_conn;
|
||||
|
||||
SIGNAL_INIT( "MediaPlayer2.TrackList",
|
||||
DBUS_MPRIS_OBJECT_PATH,
|
||||
"TrackRemoved" );
|
||||
|
||||
OUT_ARGUMENTS;
|
||||
|
||||
if ( MarshalTrack( &args, index ) != VLC_SUCCESS )
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
|
||||
SIGNAL_SEND;
|
||||
}
|
||||
/**
|
||||
* TrackListPropertiesChangedEmit: Emits the following signals:
|
||||
* - org.freedesktop.DBus.Properties.PropertiesChanged
|
||||
* - org.mpris.MediaPlayer2.TrackList.TrackAdded
|
||||
*/
|
||||
int TrackListPropertiesChangedEmit( intf_thread_t * p_intf,
|
||||
vlc_dictionary_t * p_changed_properties )
|
||||
@ -477,5 +583,35 @@ int TrackListPropertiesChangedEmit( intf_thread_t * p_intf,
|
||||
return VLC_SUCCESS;
|
||||
|
||||
PropertiesChangedSignal( p_intf, p_changed_properties );
|
||||
|
||||
if( vlc_dictionary_has_key( p_changed_properties, "TrackAdded" ) ) {
|
||||
tracklist_append_event_t *added_tracks =
|
||||
vlc_dictionary_value_for_key( p_changed_properties, "TrackAdded" );
|
||||
|
||||
while (added_tracks) {
|
||||
for (size_t i = 0; i < added_tracks->change_ev.count; ++i) {
|
||||
TrackAddedSignal( p_intf,
|
||||
added_tracks->change_ev.index + i,
|
||||
added_tracks->items[i] );
|
||||
}
|
||||
added_tracks = tracklist_append_event_next(added_tracks);
|
||||
}
|
||||
tracklist_append_event_destroy( added_tracks );
|
||||
}
|
||||
|
||||
if( vlc_dictionary_has_key( p_changed_properties, "TrackRemoved" ) ) {
|
||||
tracklist_remove_event_t *removed_tracks =
|
||||
vlc_dictionary_value_for_key( p_changed_properties, "TrackRemoved" );
|
||||
|
||||
while (removed_tracks) {
|
||||
for (size_t i = 0; i < removed_tracks->change_ev.count; ++i) {
|
||||
TrackRemovedSignal( p_intf, removed_tracks->change_ev.index + i );
|
||||
}
|
||||
removed_tracks = tracklist_remove_event_next(removed_tracks);
|
||||
}
|
||||
|
||||
tracklist_remove_event_destroy( removed_tracks );
|
||||
}
|
||||
|
||||
return VLC_SUCCESS;
|
||||
}
|
||||
|
@ -36,6 +36,61 @@
|
||||
#define DBUS_MPRIS_NOTRACK "/org/mpris/MediaPlayer2/TrackList/NoTrack"
|
||||
#define DBUS_MPRIS_APPEND "/org/mpris/MediaPlayer2/TrackList/Append"
|
||||
|
||||
struct tracklist_change_event {
|
||||
size_t index;
|
||||
size_t count;
|
||||
struct tracklist_change_event *next;
|
||||
};
|
||||
|
||||
struct tracklist_append_event {
|
||||
struct tracklist_change_event change_ev;
|
||||
vlc_playlist_item_t *items[];
|
||||
};
|
||||
|
||||
struct tracklist_remove_event {
|
||||
struct tracklist_change_event change_ev;
|
||||
};
|
||||
|
||||
typedef struct tracklist_append_event tracklist_append_event_t;
|
||||
typedef struct tracklist_remove_event tracklist_remove_event_t;
|
||||
|
||||
/* Creates an event holding what items have been appended to a tracklist.
|
||||
* The event data will be used to generate TrackAdded DBus signals later on.
|
||||
*/
|
||||
tracklist_append_event_t *
|
||||
tracklist_append_event_create( size_t index,
|
||||
vlc_playlist_item_t *const items[],
|
||||
size_t count );
|
||||
|
||||
/* Creates an event holding what items have been removed from a tracklist.
|
||||
* The event data will be used to generate TrackRemoved DBus signals later on.
|
||||
*/
|
||||
tracklist_remove_event_t *
|
||||
tracklist_remove_event_create( size_t index, size_t count );
|
||||
|
||||
/* Releases any resources reserved for this event */
|
||||
void tracklist_append_event_destroy( tracklist_append_event_t *event );
|
||||
void tracklist_remove_event_destroy( tracklist_remove_event_t *event );
|
||||
|
||||
/* Gets next event in the list */
|
||||
static tracklist_append_event_t *
|
||||
tracklist_append_event_next( tracklist_append_event_t *event ) {
|
||||
if( !event )
|
||||
return NULL;
|
||||
char *p = (char *) event->change_ev.next;
|
||||
return (tracklist_append_event_t *)
|
||||
(p - offsetof(struct tracklist_append_event, change_ev));
|
||||
}
|
||||
|
||||
static tracklist_remove_event_t *
|
||||
tracklist_remove_event_next( tracklist_remove_event_t *event ) {
|
||||
if( !event )
|
||||
return NULL;
|
||||
char *p = (char *) event->change_ev.next;
|
||||
return (tracklist_remove_event_t *)
|
||||
(p - offsetof(struct tracklist_remove_event, change_ev));
|
||||
}
|
||||
|
||||
/* Handle incoming dbus messages */
|
||||
DBusHandlerResult handle_tracklist ( DBusConnection *p_conn,
|
||||
DBusMessage *p_from,
|
||||
|
Loading…
Reference in New Issue
Block a user