dbus: Implement the MPRIS v2.1, as published on http://www.mpris.org
[vlc.git] / modules / control / dbus / dbus_tracklist.c
1 /*****************************************************************************
2  * dbus-tracklist.c : dbus control module (mpris v1.0) - /TrackList object
3  *****************************************************************************
4  * Copyright © 2006-2008 Rafaël Carré
5  * Copyright © 2007-2010 Mirsal Ennaime
6  * Copyright © 2009-2010 The VideoLAN team
7  * $Id$
8  *
9  * Authors:    Mirsal Ennaime <mirsal at mirsal fr>
10  *             Rafaël Carré <funman at videolanorg>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_playlist.h>
33
34 #include <assert.h>
35
36 #include "dbus_tracklist.h"
37 #include "dbus_common.h"
38
39 DBUS_METHOD( AddTrack )
40 { /* add the string to the playlist, and play it if the boolean is true */
41     REPLY_INIT;
42     OUT_ARGUMENTS;
43
44     DBusError error;
45     dbus_error_init( &error );
46
47     char *psz_mrl;
48     dbus_bool_t b_play;
49
50     dbus_message_get_args( p_from, &error,
51             DBUS_TYPE_STRING, &psz_mrl,
52             DBUS_TYPE_BOOLEAN, &b_play,
53             DBUS_TYPE_INVALID );
54
55     if( dbus_error_is_set( &error ) )
56     {
57         msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
58                 error.message );
59         dbus_error_free( &error );
60         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
61     }
62
63     playlist_Add( PL, psz_mrl, NULL, PLAYLIST_APPEND |
64             ( ( b_play == TRUE ) ? PLAYLIST_GO : 0 ) ,
65             PLAYLIST_END, true, false );
66
67     dbus_int32_t i_success = 0;
68     ADD_INT32( &i_success );
69
70     REPLY_SEND;
71 }
72
73 DBUS_METHOD( GetCurrentTrack )
74 {
75     REPLY_INIT;
76     OUT_ARGUMENTS;
77
78     playlist_t *p_playlist = PL;
79
80     PL_LOCK;
81     dbus_int32_t i_position = PL->i_current_index;
82     PL_UNLOCK;
83
84     ADD_INT32( &i_position );
85     REPLY_SEND;
86 }
87
88 DBUS_METHOD( GetMetadata )
89 {
90     REPLY_INIT;
91     OUT_ARGUMENTS;
92     DBusError error;
93     dbus_error_init( &error );
94
95     dbus_int32_t i_position;
96     playlist_t *p_playlist = PL;
97
98     dbus_message_get_args( p_from, &error,
99            DBUS_TYPE_INT32, &i_position,
100            DBUS_TYPE_INVALID );
101
102     if( dbus_error_is_set( &error ) )
103     {
104         msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
105                 error.message );
106         dbus_error_free( &error );
107         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
108     }
109
110     PL_LOCK;
111     if( i_position < p_playlist->current.i_size )
112     {
113         GetInputMeta( p_playlist->current.p_elems[i_position]->p_input, &args );
114     }
115
116     PL_UNLOCK;
117     REPLY_SEND;
118 }
119
120 DBUS_METHOD( GetLength )
121 {
122     REPLY_INIT;
123     OUT_ARGUMENTS;
124     playlist_t *p_playlist = PL;
125
126     PL_LOCK;
127     dbus_int32_t i_elements = PL->current.i_size;
128     PL_UNLOCK;
129
130     ADD_INT32( &i_elements );
131     REPLY_SEND;
132 }
133
134 DBUS_METHOD( DelTrack )
135 {
136     REPLY_INIT;
137
138     DBusError error;
139     dbus_error_init( &error );
140
141     dbus_int32_t i_position;
142     playlist_t *p_playlist = PL;
143
144     dbus_message_get_args( p_from, &error,
145             DBUS_TYPE_INT32, &i_position,
146             DBUS_TYPE_INVALID );
147
148     if( dbus_error_is_set( &error ) )
149     {
150         msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
151                 error.message );
152         dbus_error_free( &error );
153         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
154     }
155
156     PL_LOCK;
157     if( i_position < p_playlist->current.i_size )
158     {
159         playlist_DeleteFromInput( p_playlist,
160             p_playlist->current.p_elems[i_position]->p_input,
161             pl_Locked );
162     }
163     PL_UNLOCK;
164
165     REPLY_SEND;
166 }
167
168 DBUS_METHOD( SetLoop )
169 {
170     REPLY_INIT;
171     OUT_ARGUMENTS;
172
173     DBusError error;
174     dbus_bool_t b_loop;
175
176     dbus_error_init( &error );
177     dbus_message_get_args( p_from, &error,
178             DBUS_TYPE_BOOLEAN, &b_loop,
179             DBUS_TYPE_INVALID );
180
181     if( dbus_error_is_set( &error ) )
182     {
183         msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
184                 error.message );
185         dbus_error_free( &error );
186         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
187     }
188
189     var_SetBool( PL, "loop", ( b_loop == TRUE ) );
190
191     REPLY_SEND;
192 }
193
194 DBUS_METHOD( SetRandom )
195 {
196     REPLY_INIT;
197     OUT_ARGUMENTS;
198
199     DBusError error;
200     dbus_bool_t b_random;
201
202     dbus_error_init( &error );
203     dbus_message_get_args( p_from, &error,
204             DBUS_TYPE_BOOLEAN, &b_random,
205             DBUS_TYPE_INVALID );
206
207     if( dbus_error_is_set( &error ) )
208     {
209         msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
210                 error.message );
211         dbus_error_free( &error );
212         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
213     }
214
215     var_SetBool( PL, "random", ( b_random == TRUE ) );
216
217     REPLY_SEND;
218 }
219
220 /******************************************************************************
221  * TrackListChange: tracklist order / length change signal
222  *****************************************************************************/
223 DBUS_SIGNAL( TrackListChangeSignal )
224 { /* emit the new tracklist lengh */
225     SIGNAL_INIT( DBUS_MPRIS_TRACKLIST_INTERFACE,
226                  DBUS_MPRIS_TRACKLIST_PATH,
227                  "TrackListChange");
228
229     OUT_ARGUMENTS;
230
231     playlist_t *p_playlist = ((intf_thread_t*)p_data)->p_sys->p_playlist;
232     PL_LOCK;
233     dbus_int32_t i_elements = p_playlist->current.i_size;
234     PL_UNLOCK;
235
236     ADD_INT32( &i_elements );
237     SIGNAL_SEND;
238 }
239
240 #define METHOD_FUNC( interface, method, function ) \
241     else if( dbus_message_is_method_call( p_from, interface, method ) )\
242         return function( p_conn, p_from, p_this )
243
244 DBusHandlerResult
245 handle_tracklist ( DBusConnection *p_conn, DBusMessage *p_from, void *p_this )
246 {
247     if(0);
248
249 /*  METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "Get",    GetProperty );
250     METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "Set",    SetProperty );
251     METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "GetAll", GetAllProperties ); */
252
253     /* here D-Bus method names are associated to an handler */
254
255     METHOD_FUNC( DBUS_MPRIS_TRACKLIST_INTERFACE, "GetMetadata",     GetMetadata );
256     METHOD_FUNC( DBUS_MPRIS_TRACKLIST_INTERFACE, "GetCurrentTrack", GetCurrentTrack );
257     METHOD_FUNC( DBUS_MPRIS_TRACKLIST_INTERFACE, "GetLength",       GetLength );
258     METHOD_FUNC( DBUS_MPRIS_TRACKLIST_INTERFACE, "AddTrack",        AddTrack );
259     METHOD_FUNC( DBUS_MPRIS_TRACKLIST_INTERFACE, "DelTrack",        DelTrack );
260     METHOD_FUNC( DBUS_MPRIS_TRACKLIST_INTERFACE, "SetLoop",         SetLoop );
261     METHOD_FUNC( DBUS_MPRIS_TRACKLIST_INTERFACE, "SetRandom",       SetRandom );
262
263     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
264 }
265
266 /*****************************************************************************
267  * TrackListChangeEmit: Emits the TrackListChange signal
268  *****************************************************************************/
269 /* FIXME: It is not called on tracklist reordering */
270 int TrackListChangeEmit( intf_thread_t *p_intf, int signal, int i_node )
271 {
272     // "playlist-item-append"
273     if( signal == SIGNAL_PLAYLIST_ITEM_APPEND )
274     {
275         /* don't signal when items are added/removed in p_category */
276         playlist_t *p_playlist = p_intf->p_sys->p_playlist;
277         PL_LOCK;
278         playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_node );
279         assert( p_item );
280         while( p_item->p_parent )
281             p_item = p_item->p_parent;
282         if( p_item == p_playlist->p_root_category )
283         {
284             PL_UNLOCK;
285             return VLC_SUCCESS;
286         }
287         PL_UNLOCK;
288     }
289
290     if( p_intf->p_sys->b_dead )
291         return VLC_SUCCESS;
292
293     TrackListChangeSignal( p_intf->p_sys->p_conn, p_intf );
294     return VLC_SUCCESS;
295 }
296
297 #undef METHOD_FUNC