dbus: Implement the MPRIS v2.1, as published on http://www.mpris.org
[vlc.git] / modules / control / dbus / dbus_root.c
1 /*****************************************************************************
2  * dbus-root.c : dbus control module (mpris v1.0) - root 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_interface.h>
33
34 #include <unistd.h>
35 #include <limits.h>
36
37 #include "dbus_root.h"
38 #include "dbus_common.h"
39
40 DBUS_METHOD( Identity )
41 {
42     VLC_UNUSED(p_this);
43     REPLY_INIT;
44     OUT_ARGUMENTS;
45
46     char *psz_identity = VLC_IDENTITY;
47
48     DBusMessageIter v;
49     dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "s", &v );
50     dbus_message_iter_append_basic( &v, DBUS_TYPE_STRING, &psz_identity );
51
52     if( !dbus_message_iter_close_container( &args, &v ) )
53         return DBUS_HANDLER_RESULT_NEED_MEMORY;
54
55     REPLY_SEND;
56 }
57
58 DBUS_METHOD( CanQuit )
59 {
60     VLC_UNUSED( p_this );
61     REPLY_INIT;
62     OUT_ARGUMENTS;
63
64     const dbus_bool_t b_ret = TRUE;
65
66     DBusMessageIter v;
67     dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "s", &v );
68     dbus_message_iter_append_basic( &v, DBUS_TYPE_BOOLEAN, &b_ret );
69
70     if( !dbus_message_iter_close_container( &args, &v ) )
71         return DBUS_HANDLER_RESULT_NEED_MEMORY;
72
73     REPLY_SEND;
74 }
75
76 DBUS_METHOD( CanRaise )
77 {
78     VLC_UNUSED( p_this );
79     REPLY_INIT;
80     OUT_ARGUMENTS;
81
82     const dbus_bool_t b_ret = FALSE;
83
84     DBusMessageIter v;
85     dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "s", &v );
86     dbus_message_iter_append_basic( &v, DBUS_TYPE_BOOLEAN, &b_ret );
87
88     if( !dbus_message_iter_close_container( &args, &v ) )
89         return DBUS_HANDLER_RESULT_NEED_MEMORY;
90
91     REPLY_SEND;
92 }
93
94 DBUS_METHOD( HasTrackList )
95 {
96     VLC_UNUSED( p_this );
97     REPLY_INIT;
98     OUT_ARGUMENTS;
99
100     const dbus_bool_t b_ret = FALSE;
101
102     DBusMessageIter v;
103     dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "s", &v );
104     dbus_message_iter_append_basic( &v, DBUS_TYPE_BOOLEAN, &b_ret );
105
106     if( !dbus_message_iter_close_container( &args, &v ) )
107         return DBUS_HANDLER_RESULT_NEED_MEMORY;
108
109     REPLY_SEND;
110 }
111
112 DBUS_METHOD( DesktopEntry )
113 {
114     VLC_UNUSED( p_this );
115     REPLY_INIT;
116     OUT_ARGUMENTS;
117
118     const char* psz_ret = PACKAGE;
119
120     DBusMessageIter v;
121     dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "s", &v );
122     dbus_message_iter_append_basic( &v, DBUS_TYPE_STRING, &psz_ret );
123
124     if( !dbus_message_iter_close_container( &args, &v ) )
125         return DBUS_HANDLER_RESULT_NEED_MEMORY;
126
127     REPLY_SEND;
128 }
129
130 DBUS_METHOD( SupportedMimeTypes )
131 {
132     VLC_UNUSED( p_this );
133     REPLY_INIT;
134     OUT_ARGUMENTS;
135
136     DBusMessageIter ret, v;
137     dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "s", &v );
138     size_t i_len = sizeof( ppsz_supported_mime_types ) / sizeof( char* );
139
140     if( !dbus_message_iter_open_container( &v, DBUS_TYPE_ARRAY, "s", &ret ) )
141         return DBUS_HANDLER_RESULT_NEED_MEMORY;
142
143     for( size_t i = 0; i < i_len; ++i )
144         if( !dbus_message_iter_append_basic( &ret, DBUS_TYPE_STRING,
145                                              &ppsz_supported_mime_types[i] ) )
146             return DBUS_HANDLER_RESULT_NEED_MEMORY;
147
148     if( !dbus_message_iter_close_container( &v, &ret ) )
149         return DBUS_HANDLER_RESULT_NEED_MEMORY;
150
151     if( !dbus_message_iter_close_container( &args, &v ) )
152         return DBUS_HANDLER_RESULT_NEED_MEMORY;
153
154     REPLY_SEND;
155 }
156
157 DBUS_METHOD( SupportedUriSchemes )
158 {
159     VLC_UNUSED( p_this );
160     REPLY_INIT;
161     OUT_ARGUMENTS;
162
163     DBusMessageIter ret, v;
164     dbus_message_iter_open_container( &args, DBUS_TYPE_VARIANT, "s", &v );
165     size_t i_len = sizeof( ppsz_supported_uri_schemes ) / sizeof( char* );
166
167     if( !dbus_message_iter_open_container( &v, DBUS_TYPE_ARRAY, "s", &ret ) )
168         return DBUS_HANDLER_RESULT_NEED_MEMORY;
169
170     for( size_t i = 0; i < i_len; ++i )
171         if( !dbus_message_iter_append_basic( &ret, DBUS_TYPE_STRING,
172                                              &ppsz_supported_uri_schemes[i] ) )
173             return DBUS_HANDLER_RESULT_NEED_MEMORY;
174
175     if( !dbus_message_iter_close_container( &v, &ret ) )
176         return DBUS_HANDLER_RESULT_NEED_MEMORY;
177
178     if( !dbus_message_iter_close_container( &args, &v ) )
179         return DBUS_HANDLER_RESULT_NEED_MEMORY;
180
181     REPLY_SEND;
182 }
183
184 DBUS_METHOD( Quit )
185 { /* exits vlc */
186     REPLY_INIT;
187     libvlc_Quit(INTF->p_libvlc);
188     REPLY_SEND;
189 }
190
191 #define PROPERTY_MAPPING_BEGIN if( 0 ) {}
192 #define PROPERTY_FUNC( interface, property, function ) \
193     else if( !strcmp( psz_interface_name, interface ) && \
194              !strcmp( psz_property_name,  property ) ) \
195         return function( p_conn, p_from, p_this );
196 #define PROPERTY_MAPPING_END return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
197
198 DBUS_METHOD( GetProperty )
199 {
200     DBusError error;
201
202     char *psz_interface_name = NULL;
203     char *psz_property_name  = NULL;
204
205     dbus_error_init( &error );
206     dbus_message_get_args( p_from, &error,
207             DBUS_TYPE_STRING, &psz_interface_name,
208             DBUS_TYPE_STRING, &psz_property_name,
209             DBUS_TYPE_INVALID );
210
211     if( dbus_error_is_set( &error ) )
212     {
213         msg_Err( (vlc_object_t*) p_this, "D-Bus message reading : %s",
214                                          error.message );
215         dbus_error_free( &error );
216         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
217     }
218
219     msg_Dbg( (vlc_object_t*) p_this, "Getting property %s",
220                                      psz_property_name );
221
222     PROPERTY_MAPPING_BEGIN
223     PROPERTY_FUNC( DBUS_MPRIS_ROOT_INTERFACE, "Identity",            Identity )
224     PROPERTY_FUNC( DBUS_MPRIS_ROOT_INTERFACE, "DesktopEntry",        DesktopEntry )
225     PROPERTY_FUNC( DBUS_MPRIS_ROOT_INTERFACE, "SupportedMimeTypes",  SupportedMimeTypes )
226     PROPERTY_FUNC( DBUS_MPRIS_ROOT_INTERFACE, "SupportedUriSchemes", SupportedUriSchemes )
227     PROPERTY_FUNC( DBUS_MPRIS_ROOT_INTERFACE, "HasTrackList",        HasTrackList )
228     PROPERTY_FUNC( DBUS_MPRIS_ROOT_INTERFACE, "CanQuit",             CanQuit )
229     PROPERTY_FUNC( DBUS_MPRIS_ROOT_INTERFACE, "CanRaise",            CanRaise )
230     PROPERTY_MAPPING_END
231 }
232
233 #undef PROPERTY_MAPPING_BEGIN
234 #undef PROPERTY_GET_FUNC
235 #undef PROPERTY_MAPPING_END
236
237 #define METHOD_MAPPING_BEGIN if( 0 ) {}
238 #define METHOD_FUNC( interface, method, function ) \
239     else if( dbus_message_is_method_call( p_from, interface, method ) )\
240         return function( p_conn, p_from, p_this )
241 #define METHOD_MAPPING_END return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
242
243 DBusHandlerResult
244 handle_root ( DBusConnection *p_conn, DBusMessage *p_from, void *p_this )
245 {
246     METHOD_MAPPING_BEGIN
247     METHOD_FUNC( DBUS_INTERFACE_PROPERTIES, "Get",          GetProperty );
248     METHOD_FUNC( DBUS_MPRIS_ROOT_INTERFACE, "Quit",         Quit );
249     METHOD_MAPPING_END
250 }
251
252 #undef METHOD_MAPPING_BEGIN
253 #undef METHOD_FUNC
254 #undef METHOD_MAPPING_END