~ubuntu-branches/ubuntu/utopic/rhythmbox/utopic-proposed

« back to all changes in this revision

Viewing changes to remote/bonobo/rb-remote-bonobo.c

Tags: upstream-0.9.2
ImportĀ upstreamĀ versionĀ 0.9.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  arch-tag: Implementation of Rhythmbox Bonobo remoting
 
3
 *
 
4
 *  Copyright (C) 2004 Colin Walters <walters@gnome.org>
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2, or (at your option)
 
9
 *  any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
19
 *
 
20
 */
 
21
 
 
22
#include "rb-remote-bonobo.h"
 
23
#include "rb-remote-client-proxy.h"
 
24
#include <Rhythmbox.h>
 
25
#include <bonobo/bonobo-arg.h>
 
26
#include <bonobo/bonobo-main.h>
 
27
#include <bonobo/bonobo-context.h>
 
28
#include <bonobo/bonobo-exception.h>
 
29
#include <bonobo/bonobo-window.h>
 
30
#include <bonobo/bonobo-control-frame.h>
 
31
#include <bonobo-activation/bonobo-activation-register.h>
 
32
#include <gtk/gtk.h>
 
33
#include <gdk/gdk.h>
 
34
#include <config.h>
 
35
#include <string.h>
 
36
#include <libgnome/libgnome.h>
 
37
#include <libgnome/gnome-i18n.h>
 
38
 
 
39
#include "rb-debug.h"
 
40
 
 
41
static void rb_remote_bonobo_class_init (RBRemoteBonoboClass *klass);
 
42
static void rb_remote_bonobo_remote_client_proxy_init (RBRemoteClientProxyIface *iface);
 
43
static void rb_remote_bonobo_init (RBRemoteBonobo *shell);
 
44
static void rb_remote_bonobo_dispose (GObject *object);
 
45
static void rb_remote_bonobo_finalize (GObject *object);
 
46
 
 
47
/* Server methods */
 
48
static void rb_remote_bonobo_corba_quit (PortableServer_Servant _servant,
 
49
                                         CORBA_Environment *ev);
 
50
static void rb_remote_bonobo_corba_handle_file (PortableServer_Servant _servant,
 
51
                                                const CORBA_char *uri,
 
52
                                                CORBA_Environment *ev);
 
53
static void rb_remote_bonobo_corba_add_to_library (PortableServer_Servant _servant,
 
54
                                                   const CORBA_char *uri,
 
55
                                                   CORBA_Environment *ev);
 
56
static void rb_remote_bonobo_corba_grab_focus (PortableServer_Servant _servant,
 
57
                                               CORBA_Environment *ev);
 
58
static void rb_remote_bonobo_corba_playpause (PortableServer_Servant _servant,
 
59
                                              CORBA_Environment *ev);
 
60
static void rb_remote_bonobo_corba_select (PortableServer_Servant _servant,
 
61
                                           const CORBA_char *uri,
 
62
                                           CORBA_Environment *ev);
 
63
static void rb_remote_bonobo_corba_play (PortableServer_Servant _servant,
 
64
                                         const CORBA_char *uri,
 
65
                                         CORBA_Environment *ev);
 
66
static void rb_remote_bonobo_corba_next (PortableServer_Servant _servant,
 
67
                                         CORBA_Environment *ev);
 
68
static void rb_remote_bonobo_corba_previous (PortableServer_Servant _servant,
 
69
                                             CORBA_Environment *ev);
 
70
static CORBA_long rb_remote_bonobo_corba_get_playing_time (PortableServer_Servant _servant,
 
71
                                                   CORBA_Environment *ev);
 
72
static void rb_remote_bonobo_corba_set_playing_time (PortableServer_Servant _servant,
 
73
                                                   CORBA_long time, CORBA_Environment *ev);
 
74
static void rb_remote_bonobo_corba_skip (PortableServer_Servant _servant,
 
75
                                         CORBA_long offset, CORBA_Environment *ev);
 
76
static void rb_remote_bonobo_corba_set_rating (PortableServer_Servant _servant,
 
77
                                               CORBA_double rating, CORBA_Environment *ev);
 
78
static void rb_remote_bonobo_corba_toggle_mute (PortableServer_Servant _servant,
 
79
                                                CORBA_Environment *ev);
 
80
 
 
81
static Bonobo_PropertyBag rb_remote_bonobo_corba_get_player_properties (PortableServer_Servant _servant, CORBA_Environment *ev);
 
82
 
 
83
/* Server signal handlers */
 
84
static void rb_remote_bonobo_song_changed_cb (RBRemoteProxy *proxy,
 
85
                                              const RBRemoteSong *song,
 
86
                                              RBRemoteBonobo *bonobo);
 
87
static void rb_remote_bonobo_visibility_changed_cb (RBRemoteProxy *proxy, 
 
88
                                                    gboolean visible,
 
89
                                                    RBRemoteBonobo *bonobo);
 
90
static void rb_remote_bonobo_player_notify_cb (GObject *object,
 
91
                                               GParamSpec *param,
 
92
                                               RBRemoteBonobo *bonobo);
 
93
 
 
94
/* Client methods */
 
95
static void rb_remote_bonobo_client_handle_uri_impl (RBRemoteClientProxy *proxy, const char *uri);
 
96
static RBRemoteSong *rb_remote_bonobo_client_get_playing_song_impl (RBRemoteClientProxy *proxy);
 
97
static void rb_remote_bonobo_client_grab_focus_impl (RBRemoteClientProxy *proxy);
 
98
static void rb_remote_bonobo_client_toggle_visibility_impl (RBRemoteClientProxy *proxy);
 
99
static void rb_remote_bonobo_client_set_visibility_impl (RBRemoteClientProxy *proxy, gboolean visible);
 
100
static gboolean rb_remote_bonobo_client_get_visibility_impl (RBRemoteClientProxy *proxy);
 
101
static void rb_remote_bonobo_client_toggle_shuffle_impl (RBRemoteClientProxy *proxy);
 
102
static void rb_remote_bonobo_client_set_shuffle_impl (RBRemoteClientProxy *proxy, gboolean visible);
 
103
static gboolean rb_remote_bonobo_client_get_shuffle_impl (RBRemoteClientProxy *proxy);
 
104
static void rb_remote_bonobo_client_toggle_repeat_impl (RBRemoteClientProxy *proxy);
 
105
static void rb_remote_bonobo_client_set_repeat_impl (RBRemoteClientProxy *proxy, gboolean visible);
 
106
static gboolean rb_remote_bonobo_client_get_repeat_impl (RBRemoteClientProxy *proxy);
 
107
static void rb_remote_bonobo_client_toggle_playing_impl (RBRemoteClientProxy *proxy);
 
108
static void rb_remote_bonobo_client_play_impl (RBRemoteClientProxy *proxy);
 
109
static void rb_remote_bonobo_client_pause_impl (RBRemoteClientProxy *proxy);
 
110
static long rb_remote_bonobo_client_get_playing_time_impl (RBRemoteClientProxy *proxy);
 
111
static void rb_remote_bonobo_client_set_playing_time_impl (RBRemoteClientProxy *proxy, long time);
 
112
static void rb_remote_bonobo_client_jump_next_impl (RBRemoteClientProxy *proxy);
 
113
static void rb_remote_bonobo_client_jump_previous_impl (RBRemoteClientProxy *proxy);
 
114
static void rb_remote_bonobo_client_quit_impl (RBRemoteClientProxy *proxy);
 
115
 
 
116
static void rb_remote_bonobo_client_set_rating_impl (RBRemoteClientProxy *proxy, double rating);
 
117
static void rb_remote_bonobo_client_seek_impl (RBRemoteClientProxy *proxy, long offset);
 
118
static void rb_remote_bonobo_client_set_volume_impl (RBRemoteClientProxy *proxy, float volume);
 
119
static float rb_remote_bonobo_client_get_volume_impl (RBRemoteClientProxy *proxy);
 
120
static void rb_remote_bonobo_client_toggle_mute_impl (RBRemoteClientProxy *proxy);
 
121
 
 
122
 
 
123
static GObjectClass *parent_class;
 
124
 
 
125
enum
 
126
{
 
127
        PROP_0,
 
128
        PROP_VISIBILITY,
 
129
        PROP_SHUFFLE,
 
130
        PROP_REPEAT,
 
131
        PROP_SONG,
 
132
        PROP_LAST_STATIC
 
133
};
 
134
 
 
135
struct RBRemoteBonoboPrivate
 
136
{
 
137
        gboolean disposed;
 
138
 
 
139
        GNOME_Rhythmbox remote;
 
140
        
 
141
        RBRemoteProxy *proxy;
 
142
 
 
143
        BonoboPropertyBag *pb;
 
144
 
 
145
        guint next_property;
 
146
        GParamSpec *property_spec[16];
 
147
};
 
148
 
 
149
GType
 
150
rb_remote_bonobo_get_type (void)
 
151
{
 
152
        static GType type = 0;
 
153
                                                                              
 
154
        if (type == 0)
 
155
        { 
 
156
                static GTypeInfo info =
 
157
                {
 
158
                        sizeof (RBRemoteBonoboClass),
 
159
                        NULL, 
 
160
                        NULL,
 
161
                        (GClassInitFunc) rb_remote_bonobo_class_init, 
 
162
                        NULL,
 
163
                        NULL, 
 
164
                        sizeof (RBRemoteBonobo),
 
165
                        0,
 
166
                        (GInstanceInitFunc) rb_remote_bonobo_init
 
167
                };
 
168
 
 
169
                static const GInterfaceInfo rb_remote_client_proxy_info =
 
170
                {
 
171
                        (GInterfaceInitFunc) rb_remote_bonobo_remote_client_proxy_init,
 
172
                        NULL,
 
173
                        NULL
 
174
                };
 
175
                
 
176
                type = bonobo_type_unique (BONOBO_TYPE_OBJECT,
 
177
                                           POA_GNOME_Rhythmbox__init,
 
178
                                           POA_GNOME_Rhythmbox__fini,
 
179
                                           G_STRUCT_OFFSET (RBRemoteBonoboClass, epv),
 
180
                                           &info,
 
181
                                           "RBRemoteBonobo");
 
182
 
 
183
                g_type_add_interface_static (type,
 
184
                                             RB_TYPE_REMOTE_CLIENT_PROXY,
 
185
                                             &rb_remote_client_proxy_info);
 
186
        }
 
187
 
 
188
        return type;
 
189
}
 
190
 
 
191
static void
 
192
rb_remote_bonobo_class_init (RBRemoteBonoboClass *klass)
 
193
{
 
194
        GObjectClass *object_class = (GObjectClass *) klass;
 
195
        POA_GNOME_Rhythmbox__epv *epv = &klass->epv;
 
196
 
 
197
        parent_class = g_type_class_peek_parent (klass);
 
198
 
 
199
        object_class->dispose = rb_remote_bonobo_dispose;
 
200
        object_class->finalize = rb_remote_bonobo_finalize;
 
201
 
 
202
        epv->quit         = rb_remote_bonobo_corba_quit;
 
203
        epv->handleFile   = rb_remote_bonobo_corba_handle_file;
 
204
        epv->addToLibrary = rb_remote_bonobo_corba_add_to_library;
 
205
        epv->grabFocus    = rb_remote_bonobo_corba_grab_focus;
 
206
        epv->playPause = rb_remote_bonobo_corba_playpause;
 
207
        epv->select = rb_remote_bonobo_corba_select;
 
208
        epv->play = rb_remote_bonobo_corba_play;
 
209
        epv->previous = rb_remote_bonobo_corba_previous;
 
210
        epv->next = rb_remote_bonobo_corba_next;
 
211
        epv->getPlayingTime = rb_remote_bonobo_corba_get_playing_time;
 
212
        epv->setPlayingTime = rb_remote_bonobo_corba_set_playing_time;
 
213
        epv->getPlayerProperties = rb_remote_bonobo_corba_get_player_properties;
 
214
        epv->setRating = rb_remote_bonobo_corba_set_rating;
 
215
        epv->skip = rb_remote_bonobo_corba_skip;
 
216
        epv->toggleMute = rb_remote_bonobo_corba_toggle_mute;
 
217
}
 
218
 
 
219
static void
 
220
rb_remote_bonobo_remote_client_proxy_init (RBRemoteClientProxyIface *iface)
 
221
{
 
222
        iface->handle_uri = rb_remote_bonobo_client_handle_uri_impl;
 
223
        iface->get_playing_song = rb_remote_bonobo_client_get_playing_song_impl;
 
224
        iface->grab_focus = rb_remote_bonobo_client_grab_focus_impl;
 
225
        iface->toggle_shuffle = rb_remote_bonobo_client_toggle_shuffle_impl;
 
226
        iface->set_shuffle = rb_remote_bonobo_client_set_shuffle_impl;
 
227
        iface->get_shuffle = rb_remote_bonobo_client_get_shuffle_impl;
 
228
        iface->toggle_repeat = rb_remote_bonobo_client_toggle_repeat_impl;
 
229
        iface->set_repeat = rb_remote_bonobo_client_set_repeat_impl;
 
230
        iface->get_repeat = rb_remote_bonobo_client_get_repeat_impl;
 
231
        iface->toggle_playing = rb_remote_bonobo_client_toggle_playing_impl;
 
232
        iface->play = rb_remote_bonobo_client_play_impl;
 
233
        iface->pause = rb_remote_bonobo_client_pause_impl;
 
234
        iface->get_playing_time = rb_remote_bonobo_client_get_playing_time_impl;
 
235
        iface->set_playing_time = rb_remote_bonobo_client_set_playing_time_impl;
 
236
        iface->jump_next = rb_remote_bonobo_client_jump_next_impl;
 
237
        iface->jump_previous = rb_remote_bonobo_client_jump_previous_impl;
 
238
        iface->quit = rb_remote_bonobo_client_quit_impl;
 
239
        iface->set_rating = rb_remote_bonobo_client_set_rating_impl;
 
240
        iface->seek = rb_remote_bonobo_client_seek_impl;
 
241
        iface->set_volume = rb_remote_bonobo_client_set_volume_impl;
 
242
        iface->get_volume = rb_remote_bonobo_client_get_volume_impl;
 
243
        iface->toggle_mute = rb_remote_bonobo_client_toggle_mute_impl;
 
244
        iface->toggle_visibility = rb_remote_bonobo_client_toggle_visibility_impl;
 
245
        iface->set_visibility = rb_remote_bonobo_client_set_visibility_impl;
 
246
        iface->get_visibility = rb_remote_bonobo_client_get_visibility_impl;
 
247
}
 
248
 
 
249
/* hack to use a recursive mutex for gdk locking */
 
250
static GStaticRecMutex _rb_bonobo_mutex = G_STATIC_REC_MUTEX_INIT;
 
251
static gboolean set_lock_functions = FALSE;
 
252
 
 
253
static void
 
254
rb_bonobo_workaround_lock (void)
 
255
{
 
256
        g_static_rec_mutex_lock (&_rb_bonobo_mutex);
 
257
}
 
258
 
 
259
static void
 
260
rb_bonobo_workaround_unlock (void)
 
261
{
 
262
        g_static_rec_mutex_unlock (&_rb_bonobo_mutex);
 
263
}
 
264
 
 
265
void
 
266
rb_remote_bonobo_preinit (void)
 
267
{
 
268
 
 
269
        /*
 
270
         * By default, GDK_THREADS_ENTER/GDK_THREADS_LEAVE uses a 
 
271
         * non-recursive mutex; this leads to deadlock, as there are
 
272
         * many code paths that lead to (for example) gconf operations
 
273
         * with the gdk lock held.  While performing these gconf operations,
 
274
         * ORBit will process incoming bonobo remote interface requests.
 
275
         * The implementations of the bonobo request handlers attempt
 
276
         * to acquire the gdk lock (as far as I know this is necessary, as
 
277
         * some operations will result in UI updates etc.); if the mutex
 
278
         * does not support recursive locks, this will deadlock.
 
279
         *
 
280
         * Dropping the gdk lock before all code paths that will possibly
 
281
         * lead to a gconf operation is way too hard (they're *everywhere*),
 
282
         * and unless someone can find a way of implementing the entire
 
283
         * remote interface without needing to acquire the gdk lock, this
 
284
         * is what we're stuck with.
 
285
         *
 
286
         ***
 
287
         *
 
288
         * Note: this is why CORBA sucks.  Arbitrary reentrancy is
 
289
         * nearly impossible to get right in an application with
 
290
         * significant global state (as nearly every GUI app has). The
 
291
         * D-BUS approach of queueing requests may lead to deadlocks,
 
292
         * but it's very obvious when this happens, and it's a lot
 
293
         * easier to debug and fix.  The above approach of making the
 
294
         * GDK lock recursive only partially helps; I am certain
 
295
         * there are code paths in Rhythmbox which are not expecting
 
296
         * to be reentered, particularly in RBShellPlayer.
 
297
         */
 
298
        if (!set_lock_functions)
 
299
          {
 
300
            gdk_threads_set_lock_functions (G_CALLBACK (rb_bonobo_workaround_lock),
 
301
                                            G_CALLBACK (rb_bonobo_workaround_unlock));
 
302
            set_lock_functions = TRUE;
 
303
          }
 
304
}
 
305
 
 
306
static void
 
307
rb_remote_bonobo_init (RBRemoteBonobo *bonobo) 
 
308
{
 
309
        bonobo->priv = g_new0 (RBRemoteBonoboPrivate, 1);
 
310
}
 
311
 
 
312
static void
 
313
rb_remote_bonobo_dispose (GObject *object)
 
314
{
 
315
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (object);
 
316
 
 
317
        if (bonobo->priv->disposed)
 
318
                return;
 
319
        bonobo->priv->disposed = TRUE;
 
320
}
 
321
 
 
322
static void
 
323
rb_remote_bonobo_finalize (GObject *object)
 
324
{
 
325
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (object);
 
326
 
 
327
        g_free (bonobo->priv);
 
328
 
 
329
        (* G_OBJECT_CLASS (parent_class)->finalize) (object);
 
330
}
 
331
 
 
332
RBRemoteBonobo *
 
333
rb_remote_bonobo_new (void)
 
334
{
 
335
        return g_object_new (RB_TYPE_REMOTE_BONOBO, NULL, NULL);
 
336
}
 
337
 
 
338
 
 
339
static void
 
340
rb_remote_bonobo_corba_quit (PortableServer_Servant _servant,
 
341
                             CORBA_Environment *ev)
 
342
{
 
343
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
344
 
 
345
        GDK_THREADS_ENTER ();
 
346
        rb_remote_proxy_quit (bonobo->priv->proxy);
 
347
        GDK_THREADS_LEAVE ();
 
348
}
 
349
 
 
350
static void
 
351
rb_remote_bonobo_corba_handle_file (PortableServer_Servant _servant,
 
352
                                    const CORBA_char *uri,
 
353
                                    CORBA_Environment *ev)
 
354
{
 
355
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
356
 
 
357
        GDK_THREADS_ENTER ();
 
358
        rb_remote_proxy_load_uri (bonobo->priv->proxy, uri, TRUE);
 
359
        GDK_THREADS_LEAVE ();
 
360
}
 
361
 
 
362
static void
 
363
rb_remote_bonobo_corba_add_to_library (PortableServer_Servant _servant,
 
364
                                       const CORBA_char *uri,
 
365
                                       CORBA_Environment *ev)
 
366
{
 
367
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
368
 
 
369
        GDK_THREADS_ENTER ();
 
370
        rb_remote_proxy_load_uri (bonobo->priv->proxy, uri, FALSE);
 
371
        GDK_THREADS_LEAVE ();
 
372
}
 
373
 
 
374
static void
 
375
rb_remote_bonobo_corba_grab_focus (PortableServer_Servant _servant,
 
376
                                   CORBA_Environment *ev)
 
377
{
 
378
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
379
 
 
380
        GDK_THREADS_ENTER ();
 
381
        rb_remote_proxy_grab_focus (bonobo->priv->proxy);
 
382
        GDK_THREADS_LEAVE ();
 
383
}
 
384
 
 
385
static void
 
386
rb_remote_bonobo_corba_playpause (PortableServer_Servant _servant,
 
387
                                  CORBA_Environment *ev)
 
388
{
 
389
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
390
 
 
391
        GDK_THREADS_ENTER ();
 
392
 
 
393
        if (rb_remote_proxy_playing (bonobo->priv->proxy))
 
394
                rb_remote_proxy_pause (bonobo->priv->proxy);
 
395
        else
 
396
                rb_remote_proxy_play (bonobo->priv->proxy);
 
397
 
 
398
        GDK_THREADS_LEAVE ();
 
399
}
 
400
 
 
401
static void
 
402
rb_remote_bonobo_corba_select (PortableServer_Servant _servant,
 
403
                               const CORBA_char *uri,
 
404
                               CORBA_Environment *ev)
 
405
{
 
406
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
407
 
 
408
        GDK_THREADS_ENTER ();
 
409
        rb_remote_proxy_select_uri (bonobo->priv->proxy, uri);
 
410
        GDK_THREADS_LEAVE ();
 
411
}
 
412
 
 
413
static void
 
414
rb_remote_bonobo_corba_play (PortableServer_Servant _servant,
 
415
                             const CORBA_char *uri,
 
416
                             CORBA_Environment *ev)
 
417
{
 
418
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
419
 
 
420
        GDK_THREADS_ENTER ();
 
421
        rb_remote_proxy_play_uri (bonobo->priv->proxy, uri);
 
422
        GDK_THREADS_LEAVE ();
 
423
}
 
424
 
 
425
static void
 
426
rb_remote_bonobo_corba_next (PortableServer_Servant _servant,
 
427
                     CORBA_Environment *ev)
 
428
{
 
429
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
430
        GDK_THREADS_ENTER ();
 
431
        rb_remote_proxy_jump_next (bonobo->priv->proxy);
 
432
        GDK_THREADS_LEAVE ();
 
433
}
 
434
 
 
435
static void
 
436
rb_remote_bonobo_corba_previous (PortableServer_Servant _servant,
 
437
                                 CORBA_Environment *ev)
 
438
{
 
439
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
440
        GDK_THREADS_ENTER ();
 
441
        rb_remote_proxy_jump_previous (bonobo->priv->proxy);
 
442
        GDK_THREADS_LEAVE ();
 
443
}
 
444
 
 
445
static CORBA_long
 
446
rb_remote_bonobo_corba_get_playing_time (PortableServer_Servant _servant,
 
447
                                         CORBA_Environment *ev)
 
448
{
 
449
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
450
        long playing_time;
 
451
 
 
452
        GDK_THREADS_ENTER ();
 
453
        playing_time = rb_remote_proxy_get_playing_time (bonobo->priv->proxy);
 
454
        GDK_THREADS_LEAVE ();
 
455
 
 
456
        return (CORBA_long) playing_time;
 
457
}
 
458
 
 
459
static void
 
460
rb_remote_bonobo_corba_set_playing_time (PortableServer_Servant _servant,
 
461
                                         CORBA_long time, CORBA_Environment *ev)
 
462
{
 
463
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
464
 
 
465
        GDK_THREADS_ENTER ();
 
466
        rb_remote_proxy_set_playing_time (bonobo->priv->proxy, (long) time);
 
467
        GDK_THREADS_LEAVE ();
 
468
}
 
469
 
 
470
static void
 
471
rb_remote_bonobo_corba_skip (PortableServer_Servant _servant,
 
472
                             CORBA_long offset, CORBA_Environment *ev)
 
473
{
 
474
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
475
        GDK_THREADS_ENTER ();
 
476
        rb_remote_proxy_seek (bonobo->priv->proxy, (long) offset);
 
477
        GDK_THREADS_LEAVE ();
 
478
}
 
479
 
 
480
static void
 
481
rb_remote_bonobo_corba_set_rating (PortableServer_Servant _servant,
 
482
                                   CORBA_double rating, CORBA_Environment *ev)
 
483
{
 
484
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
485
        GDK_THREADS_ENTER ();
 
486
        rb_remote_proxy_set_rating (bonobo->priv->proxy, rating);
 
487
        GDK_THREADS_LEAVE ();
 
488
}
 
489
 
 
490
static void
 
491
rb_remote_bonobo_corba_toggle_mute (PortableServer_Servant _servant,
 
492
                                    CORBA_Environment *ev)
 
493
{
 
494
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
495
 
 
496
        GDK_THREADS_ENTER ();
 
497
        rb_remote_proxy_toggle_mute (bonobo->priv->proxy);
 
498
        GDK_THREADS_LEAVE ();
 
499
}
 
500
 
 
501
static GNOME_Rhythmbox_SongInfo *
 
502
convert_from_rb_remote_song (const RBRemoteSong *song)
 
503
{
 
504
        GNOME_Rhythmbox_SongInfo *song_info = GNOME_Rhythmbox_SongInfo__alloc ();
 
505
        song_info->title = CORBA_string_dup (song->title);
 
506
        song_info->artist = CORBA_string_dup (song->artist);
 
507
        song_info->album = CORBA_string_dup (song->album);
 
508
        song_info->genre = CORBA_string_dup (song->genre);
 
509
        song_info->path = CORBA_string_dup (song->uri);
 
510
        song_info->track_number = song->track_number;
 
511
        song_info->duration = song->duration;
 
512
        song_info->bitrate = song->bitrate;
 
513
        song_info->filesize = song->filesize;
 
514
        song_info->rating = (long)song->rating;
 
515
        song_info->play_count = song->play_count;
 
516
        song_info->last_played = song->last_played;
 
517
        return song_info;
 
518
}
 
519
 
 
520
static GNOME_Rhythmbox_SongInfo *
 
521
get_song_info_from_player (RBRemoteProxy *proxy)
 
522
{
 
523
        gchar *uri;
 
524
        RBRemoteSong *song = NULL;
 
525
        GNOME_Rhythmbox_SongInfo *song_info = NULL;
 
526
 
 
527
        GDK_THREADS_ENTER ();
 
528
        uri = rb_remote_proxy_get_playing_uri (proxy);
 
529
        if (uri != NULL) {
 
530
                song = g_new0 (RBRemoteSong, 1);
 
531
                if (song != NULL) {
 
532
                        if (rb_remote_proxy_get_song_info (proxy, uri, song) == TRUE) {
 
533
                                song_info = convert_from_rb_remote_song (song);
 
534
                        }
 
535
                        rb_remote_song_free (song);
 
536
                }
 
537
        }
 
538
        GDK_THREADS_LEAVE ();
 
539
        g_free (uri);
 
540
        
 
541
        return song_info;
 
542
}
 
543
 
 
544
static void
 
545
bonobo_pb_get_prop (BonoboPropertyBag *bag,
 
546
                    BonoboArg         *arg,
 
547
                    guint              arg_id,
 
548
                    CORBA_Environment *ev,
 
549
                    gpointer           user_data)
 
550
{
 
551
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (user_data);
 
552
 
 
553
        if ((arg_id >= PROP_LAST_STATIC) && 
 
554
            (arg_id < (bonobo->priv->next_property + PROP_LAST_STATIC))) {
 
555
                GValue value = {0};
 
556
                RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (user_data);
 
557
                GParamSpec *param = bonobo->priv->property_spec[arg_id - PROP_LAST_STATIC];
 
558
 
 
559
                g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (param));
 
560
                GDK_THREADS_ENTER ();
 
561
                rb_remote_proxy_get_player_property (bonobo->priv->proxy, 
 
562
                                                     param->name,
 
563
                                                     &value);
 
564
                GDK_THREADS_LEAVE ();
 
565
                bonobo_arg_from_gvalue (arg, &value);
 
566
                g_value_unset (&value);
 
567
                return;
 
568
        }
 
569
        
 
570
        switch (arg_id) {
 
571
 
 
572
        case PROP_VISIBILITY:
 
573
        {
 
574
                gboolean visibility;
 
575
                GDK_THREADS_ENTER ();
 
576
                visibility = rb_remote_proxy_get_visibility (bonobo->priv->proxy);
 
577
                GDK_THREADS_LEAVE ();
 
578
                BONOBO_ARG_SET_BOOLEAN (arg, visibility);
 
579
                break;
 
580
        }
 
581
 
 
582
        case PROP_SHUFFLE:
 
583
        {
 
584
                gboolean shuffle;
 
585
                GDK_THREADS_ENTER ();
 
586
                shuffle = rb_remote_proxy_get_shuffle (bonobo->priv->proxy);
 
587
                GDK_THREADS_LEAVE ();
 
588
                BONOBO_ARG_SET_BOOLEAN (arg, shuffle);
 
589
                break;
 
590
        }
 
591
 
 
592
        case PROP_REPEAT:
 
593
        {
 
594
                gboolean repeat;
 
595
                GDK_THREADS_ENTER ();
 
596
                repeat = rb_remote_proxy_get_repeat (bonobo->priv->proxy);
 
597
                GDK_THREADS_LEAVE ();
 
598
                BONOBO_ARG_SET_BOOLEAN (arg, repeat);
 
599
                break;
 
600
        }
 
601
 
 
602
        case PROP_SONG: 
 
603
        {
 
604
                GNOME_Rhythmbox_SongInfo *ret_val;
 
605
                
 
606
                ret_val = get_song_info_from_player (bonobo->priv->proxy);
 
607
                arg->_value = (gpointer)ret_val;
 
608
                if (ret_val == NULL) {
 
609
                        arg->_type = TC_null;
 
610
                } else {
 
611
                        arg->_type = TC_GNOME_Rhythmbox_SongInfo;
 
612
                }
 
613
                break;
 
614
        }
 
615
 
 
616
        default:
 
617
                bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
 
618
                break;
 
619
        }
 
620
}
 
621
 
 
622
static void
 
623
bonobo_pb_set_prop (BonoboPropertyBag *bag,
 
624
                   const BonoboArg   *arg,
 
625
                   guint              arg_id,
 
626
                   CORBA_Environment *ev,
 
627
                   gpointer           user_data)
 
628
{
 
629
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (user_data);
 
630
 
 
631
        if ((arg_id >= PROP_LAST_STATIC) && 
 
632
            (arg_id < (bonobo->priv->next_property + PROP_LAST_STATIC))) {
 
633
                GValue value = {0};
 
634
                RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (user_data);
 
635
                GParamSpec *param = bonobo->priv->property_spec[arg_id - PROP_LAST_STATIC];
 
636
 
 
637
                g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (param));
 
638
                bonobo_arg_to_gvalue (&value, arg);
 
639
                GDK_THREADS_ENTER ();
 
640
                rb_remote_proxy_set_player_property (bonobo->priv->proxy, 
 
641
                                                     param->name, 
 
642
                                                     &value);
 
643
                GDK_THREADS_LEAVE ();
 
644
                g_value_unset (&value);
 
645
                return;
 
646
        }
 
647
        
 
648
        switch (arg_id) {
 
649
 
 
650
        case PROP_VISIBILITY:
 
651
        {
 
652
                gboolean visible = BONOBO_ARG_GET_BOOLEAN (arg);
 
653
                GDK_THREADS_ENTER ();
 
654
                rb_remote_proxy_set_visibility (bonobo->priv->proxy, visible);
 
655
                GDK_THREADS_LEAVE ();
 
656
                break;
 
657
        }
 
658
 
 
659
        case PROP_SONG:
 
660
                bonobo_exception_set (ev, ex_Bonobo_PropertyBag_ReadOnly);
 
661
                break;
 
662
 
 
663
        case PROP_SHUFFLE:
 
664
        {
 
665
                gboolean shuffle = BONOBO_ARG_GET_BOOLEAN (arg);
 
666
                GDK_THREADS_ENTER ();
 
667
                rb_remote_proxy_set_shuffle (bonobo->priv->proxy, shuffle);
 
668
                GDK_THREADS_LEAVE ();
 
669
                break;
 
670
        }
 
671
 
 
672
        case PROP_REPEAT:
 
673
        {
 
674
                gboolean repeat = BONOBO_ARG_GET_BOOLEAN (arg);
 
675
                GDK_THREADS_ENTER ();
 
676
                rb_remote_proxy_set_repeat (bonobo->priv->proxy, repeat);
 
677
                GDK_THREADS_LEAVE ();
 
678
                break;
 
679
        }
 
680
 
 
681
        default:
 
682
                bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
 
683
                break;
 
684
        }
 
685
}
 
686
 
 
687
static void
 
688
rb_remote_bonobo_add_player_property (RBRemoteBonobo *bonobo,
 
689
                                      const gchar *property,
 
690
                                      const gchar *description)
 
691
{
 
692
        guint prop_id;
 
693
        GParamSpec *param;
 
694
 
 
695
        g_assert (bonobo->priv->next_property < G_N_ELEMENTS (bonobo->priv->property_spec));
 
696
        prop_id = bonobo->priv->next_property++;
 
697
        param = rb_remote_proxy_find_player_property (bonobo->priv->proxy,
 
698
                                                                  property);
 
699
        
 
700
        bonobo->priv->property_spec[prop_id] = param;
 
701
        bonobo_property_bag_add (bonobo->priv->pb, property, 
 
702
                                 prop_id + PROP_LAST_STATIC, 
 
703
                                 bonobo_arg_type_from_gtype (G_PARAM_SPEC_VALUE_TYPE (param)), 
 
704
                                 NULL,
 
705
                                 description, 0);
 
706
 
 
707
}
 
708
 
 
709
 
 
710
static Bonobo_PropertyBag
 
711
rb_remote_bonobo_corba_get_player_properties (PortableServer_Servant _servant, 
 
712
                                      CORBA_Environment *ev)
 
713
{       
 
714
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
 
715
 
 
716
        GDK_THREADS_ENTER ();
 
717
        if (bonobo->priv->pb == NULL) {
 
718
                bonobo->priv->pb = bonobo_property_bag_new (bonobo_pb_get_prop, 
 
719
                                                            bonobo_pb_set_prop, 
 
720
                                                            bonobo);
 
721
                
 
722
                
 
723
                bonobo_property_bag_add (bonobo->priv->pb, "visibility", 
 
724
                                         PROP_VISIBILITY, BONOBO_ARG_BOOLEAN, NULL, 
 
725
                                         _("Whether the main window is visible"), 0);
 
726
 
 
727
                bonobo_property_bag_add (bonobo->priv->pb, "shuffle", 
 
728
                                         PROP_SHUFFLE, BONOBO_ARG_BOOLEAN, NULL, 
 
729
                                         _("Whether shuffle is enabled"), 0);
 
730
                
 
731
                bonobo_property_bag_add (bonobo->priv->pb, "repeat", 
 
732
                                         PROP_REPEAT, BONOBO_ARG_BOOLEAN, NULL, 
 
733
                                         _("Whether repeat is enabled"), 0);
 
734
 
 
735
                bonobo_property_bag_add (bonobo->priv->pb, "song", 
 
736
                                         PROP_SONG, TC_GNOME_Rhythmbox_SongInfo, NULL, 
 
737
                                         _("Properties for the current song"), 0);
 
738
 
 
739
                rb_remote_proxy_player_notify_handler (bonobo->priv->proxy,
 
740
                                                       G_CALLBACK (rb_remote_bonobo_player_notify_cb),
 
741
                                                       bonobo);
 
742
 
 
743
                rb_remote_bonobo_add_player_property (bonobo,
 
744
                                                      "playing",
 
745
                                                      _("Whether Rhythmbox is currently playing"));
 
746
 
 
747
                rb_remote_bonobo_add_player_property (bonobo,
 
748
                                                      "play-order",
 
749
                                                      _("What play order to use"));
 
750
 
 
751
                rb_remote_bonobo_add_player_property (bonobo,
 
752
                                                      "volume",
 
753
                                                      _("Current playback volume"));
 
754
 
 
755
        }
 
756
        GDK_THREADS_LEAVE ();
 
757
 
 
758
        /* If the creation of the property bag failed, 
 
759
         * return a corba exception
 
760
         */
 
761
        
 
762
        return bonobo_object_dup_ref (BONOBO_OBJREF (bonobo->priv->pb), NULL);
 
763
}
 
764
 
 
765
static void
 
766
rb_remote_bonobo_song_changed_cb (RBRemoteProxy *proxy,
 
767
                                  const RBRemoteSong *song,
 
768
                                  RBRemoteBonobo *bonobo)
 
769
{
 
770
        GNOME_Rhythmbox_SongInfo *song_info;
 
771
        BonoboArg *arg;
 
772
 
 
773
        if (bonobo->priv->pb == NULL)
 
774
                return;
 
775
        
 
776
        arg = bonobo_arg_new (TC_GNOME_Rhythmbox_SongInfo);
 
777
        song_info = convert_from_rb_remote_song (song);
 
778
        arg->_value = (gpointer)song_info;
 
779
        if (bonobo->priv->pb != NULL) {
 
780
                bonobo_event_source_notify_listeners_full (bonobo->priv->pb->es,
 
781
                                                           "Bonobo/Property",
 
782
                                                           "change",
 
783
                                                           "song",
 
784
                                                           arg, NULL);
 
785
        }
 
786
        
 
787
        bonobo_arg_release (arg);
 
788
}
 
789
 
 
790
static void
 
791
rb_remote_bonobo_visibility_changed_cb (RBRemoteProxy *proxy,
 
792
                                        gboolean visible,
 
793
                                        RBRemoteBonobo *bonobo)
 
794
{
 
795
        BonoboArg *arg;
 
796
 
 
797
        if (bonobo->priv->pb == NULL)
 
798
                return;
 
799
        
 
800
        arg = bonobo_arg_new (TC_CORBA_boolean);
 
801
        BONOBO_ARG_SET_BOOLEAN (arg, visible);
 
802
        bonobo_event_source_notify_listeners_full (bonobo->priv->pb->es,
 
803
                                                   "Bonobo/Property",
 
804
                                                   "change",
 
805
                                                   "visibility",
 
806
                                                   arg, NULL);
 
807
        
 
808
        bonobo_arg_release (arg);
 
809
}
 
810
                                        
 
811
 
 
812
static void
 
813
rb_remote_bonobo_player_notify_cb (GObject *object,
 
814
                                   GParamSpec *param,
 
815
                                   RBRemoteBonobo *bonobo)
 
816
{
 
817
        GValue value = {0};
 
818
        BonoboArg *arg;
 
819
        BonoboArgType arg_type;
 
820
 
 
821
        if (bonobo->priv->pb == NULL)
 
822
                return;
 
823
 
 
824
        arg_type = bonobo_arg_type_from_gtype (G_PARAM_SPEC_VALUE_TYPE (param));
 
825
        if (arg_type == 0)
 
826
                return;
 
827
        
 
828
        arg = bonobo_arg_new (arg_type);
 
829
        g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (param));
 
830
        GDK_THREADS_ENTER ();
 
831
        rb_remote_proxy_get_player_property (bonobo->priv->proxy,
 
832
                                             param->name,
 
833
                                             &value);
 
834
        GDK_THREADS_LEAVE ();
 
835
        bonobo_arg_from_gvalue (arg, &value);
 
836
        bonobo_event_source_notify_listeners_full (bonobo->priv->pb->es,
 
837
                                                   "Bonobo/Property",
 
838
                                                   "change",
 
839
                                                   param->name,
 
840
                                                   arg, NULL);
 
841
        g_value_unset (&value);
 
842
        bonobo_arg_release (arg);
 
843
}
 
844
 
 
845
GQuark
 
846
rb_remote_bonobo_error_quark (void)
 
847
{
 
848
        static GQuark quark = 0;
 
849
        if (!quark)
 
850
                quark = g_quark_from_static_string ("rb_remote_bonobo_error");
 
851
 
 
852
        return quark;
 
853
}
 
854
 
 
855
static char *
 
856
rb_shell_corba_exception_to_string (CORBA_Environment *ev)
 
857
{
 
858
        g_return_val_if_fail (ev != NULL, NULL);
 
859
 
 
860
        if ((CORBA_exception_id (ev) != NULL) &&
 
861
            (strcmp (CORBA_exception_id (ev), ex_Bonobo_GeneralError) != 0))
 
862
                return bonobo_exception_get_text (ev); 
 
863
        else {
 
864
                const Bonobo_GeneralError *bonobo_general_error;
 
865
 
 
866
                bonobo_general_error = CORBA_exception_value (ev);
 
867
                if (bonobo_general_error != NULL) 
 
868
                        return g_strdup (bonobo_general_error->description);
 
869
        }
 
870
 
 
871
        return NULL;
 
872
}
 
873
 
 
874
gboolean
 
875
rb_remote_bonobo_activate (RBRemoteBonobo *bonobo)
 
876
{
 
877
        bonobo->priv->remote =
 
878
                bonobo_activation_activate_from_id (RB_REMOTE_BONOBO_OAFIID,
 
879
                                                    Bonobo_ACTIVATION_FLAG_EXISTING_ONLY,
 
880
                                                    NULL, NULL);
 
881
        return bonobo->priv->remote != NULL;
 
882
}
 
883
 
 
884
static void
 
885
shell_weak_ref_cb (gpointer data, GObject *objptr)
 
886
{
 
887
        bonobo_object_unref (BONOBO_OBJECT (data));
 
888
}
 
889
 
 
890
gboolean
 
891
rb_remote_bonobo_acquire (RBRemoteBonobo *bonobo,
 
892
                          RBRemoteProxy *proxy,
 
893
                          GError **error)
 
894
{
 
895
        CORBA_Object corba_object;
 
896
        CORBA_Environment ev;
 
897
        gboolean registration_failed;
 
898
 
 
899
        rb_debug ("registering with bonobo"); 
 
900
 
 
901
        bonobo->priv->proxy = proxy;
 
902
        g_object_weak_ref (G_OBJECT (proxy), shell_weak_ref_cb, bonobo);
 
903
 
 
904
        g_signal_connect_object (G_OBJECT (proxy),
 
905
                                 "song_changed",
 
906
                                 G_CALLBACK (rb_remote_bonobo_song_changed_cb),
 
907
                                 bonobo, 0);
 
908
                                 
 
909
        g_signal_connect_object (G_OBJECT (proxy),
 
910
                                 "visibility_changed",
 
911
                                 G_CALLBACK (rb_remote_bonobo_visibility_changed_cb),
 
912
                                 bonobo, 0);
 
913
                                 
 
914
 
 
915
        corba_object = bonobo_object_corba_objref (BONOBO_OBJECT (bonobo));
 
916
 
 
917
        registration_failed = FALSE;
 
918
        if (bonobo_activation_active_server_register (RB_REMOTE_BONOBO_OAFIID, corba_object) != Bonobo_ACTIVATION_REG_SUCCESS)
 
919
                registration_failed = TRUE;
 
920
                
 
921
        if (bonobo_activation_active_server_register (RB_FACTORY_OAFIID, corba_object) != Bonobo_ACTIVATION_REG_SUCCESS)
 
922
                registration_failed = TRUE;
 
923
                
 
924
        CORBA_exception_init (&ev);
 
925
 
 
926
        if (registration_failed) {
 
927
                char *msg = rb_shell_corba_exception_to_string (&ev);
 
928
                g_set_error (error,
 
929
                             RB_REMOTE_BONOBO_ERROR,
 
930
                             RB_REMOTE_BONOBO_ERROR_ACQUISITION_FAILURE,
 
931
                             _("Failed to register the shell: %s\n"
 
932
                               "This probably means that you installed Rhythmbox in a "
 
933
                               "different prefix than bonobo-activation; this "
 
934
                               "warning is harmless, but IPC will not work."), msg);
 
935
                g_free (msg);
 
936
                rb_debug ("failed to register with bonobo activation"); 
 
937
        } else {
 
938
                rb_debug ("successfully registered with bonobo activation"); 
 
939
        }
 
940
        CORBA_exception_free (&ev);
 
941
 
 
942
        return !registration_failed;
 
943
}
 
944
 
 
945
/* Client methods */
 
946
 
 
947
static void
 
948
rb_remote_bonobo_client_handle_uri_impl (RBRemoteClientProxy *proxy, const char *uri)
 
949
{
 
950
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
951
        CORBA_Environment ev;
 
952
 
 
953
        CORBA_exception_init (&ev);
 
954
        GNOME_Rhythmbox_handleFile (bonobo->priv->remote, uri, &ev);
 
955
        CORBA_exception_free (&ev);
 
956
}
 
957
 
 
958
static RBRemoteSong *
 
959
rb_remote_bonobo_client_get_playing_song_impl (RBRemoteClientProxy *proxy)
 
960
{
 
961
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
962
        RBRemoteSong *song = NULL;
 
963
        Bonobo_PropertyBag pb;
 
964
        CORBA_any *any;
 
965
        CORBA_Environment ev;
 
966
        GNOME_Rhythmbox_SongInfo *song_info = NULL;
 
967
 
 
968
        /*
 
969
         * Yes, this is insane.
 
970
         */
 
971
 
 
972
        CORBA_exception_init (&ev);
 
973
        pb = GNOME_Rhythmbox_getPlayerProperties (bonobo->priv->remote, &ev);
 
974
        if (BONOBO_EX (&ev)) {
 
975
                char *err = bonobo_exception_get_text (&ev);
 
976
                g_warning (_("An exception occured '%s'"), err);
 
977
                return NULL;
 
978
        }
 
979
 
 
980
        any = bonobo_pbclient_get_value (pb, "song", 
 
981
                                         TC_GNOME_Rhythmbox_SongInfo, 
 
982
                                         &ev);
 
983
        if (BONOBO_EX (&ev)) {
 
984
                char *err = bonobo_exception_get_text (&ev);
 
985
                g_warning (_("An exception occured '%s'"), err);
 
986
                g_free (err);
 
987
                bonobo_object_release_unref ((Bonobo_Unknown) pb, &ev);
 
988
                return NULL;
 
989
        }
 
990
        
 
991
        if ((any == NULL) || (!CORBA_TypeCode_equivalent (any->_type, TC_GNOME_Rhythmbox_SongInfo, NULL))) {
 
992
                song_info = NULL;
 
993
        } else {
 
994
                song_info = (GNOME_Rhythmbox_SongInfo*)any->_value;
 
995
                any->_release = FALSE;
 
996
                CORBA_free (any);
 
997
        }
 
998
 
 
999
        if (song_info != NULL) {
 
1000
                song = g_new0 (RBRemoteSong, 1);
 
1001
                song->title = g_strdup (song_info->title);
 
1002
                song->artist = g_strdup (song_info->artist);
 
1003
                song->genre = g_strdup (song_info->genre);
 
1004
                song->album = g_strdup (song_info->album);
 
1005
                song->uri = g_strdup (song_info->path);
 
1006
                song->track_number = song_info->track_number;
 
1007
                song->duration = song_info->duration;
 
1008
                song->bitrate = song_info->bitrate;
 
1009
                song->filesize = song_info->filesize;
 
1010
                song->rating = song_info->rating;
 
1011
                song->play_count = song_info->play_count;
 
1012
                song->last_played = song_info->last_played;
 
1013
                                                                        
 
1014
                CORBA_free (song_info);
 
1015
        }
 
1016
 
 
1017
        bonobo_object_release_unref ((Bonobo_Unknown) pb, &ev);
 
1018
 
 
1019
        return song;
 
1020
}
 
1021
 
 
1022
static void
 
1023
rb_remote_bonobo_client_grab_focus_impl (RBRemoteClientProxy *proxy)
 
1024
{
 
1025
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1026
        CORBA_Environment ev;
 
1027
 
 
1028
        CORBA_exception_init (&ev);
 
1029
        GNOME_Rhythmbox_grabFocus (bonobo->priv->remote, &ev);
 
1030
        CORBA_exception_free (&ev);
 
1031
}
 
1032
 
 
1033
static void
 
1034
_rb_remote_bonobo_client_toggle_property (RBRemoteBonobo *bonobo,
 
1035
                                          const char *property)
 
1036
{
 
1037
        Bonobo_PropertyBag pb;
 
1038
        gboolean v;
 
1039
        CORBA_Environment ev;
 
1040
 
 
1041
        CORBA_exception_init (&ev);
 
1042
 
 
1043
        pb = GNOME_Rhythmbox_getPlayerProperties (bonobo->priv->remote, &ev);
 
1044
 
 
1045
        v  = bonobo_pbclient_get_boolean (pb,
 
1046
                                          property,
 
1047
                                          &ev);
 
1048
        if (BONOBO_EX (&ev)) {
 
1049
                return;
 
1050
        }
 
1051
                
 
1052
        bonobo_pbclient_set_boolean (pb,
 
1053
                                     property,
 
1054
                                     v ? FALSE : TRUE,
 
1055
                                     &ev);
 
1056
        if (BONOBO_EX (&ev))
 
1057
                return;
 
1058
 
 
1059
        bonobo_object_release_unref ((Bonobo_Unknown)pb, &ev);
 
1060
}
 
1061
 
 
1062
static gboolean
 
1063
_rb_remote_bonobo_client_get_boolean_property (RBRemoteBonobo *bonobo,
 
1064
                                               const char *property)
 
1065
{
 
1066
        Bonobo_PropertyBag pb;
 
1067
        gboolean v;
 
1068
        CORBA_Environment ev;
 
1069
 
 
1070
        CORBA_exception_init (&ev);
 
1071
 
 
1072
        pb = GNOME_Rhythmbox_getPlayerProperties (bonobo->priv->remote, &ev);
 
1073
 
 
1074
        v  = bonobo_pbclient_get_boolean (pb,
 
1075
                                          property,
 
1076
                                          &ev);
 
1077
        bonobo_object_release_unref ((Bonobo_Unknown)pb, &ev);
 
1078
        return v;
 
1079
}
 
1080
 
 
1081
static void
 
1082
_rb_remote_bonobo_client_set_boolean_property (RBRemoteBonobo *bonobo,
 
1083
                                               const char *property,
 
1084
                                               gboolean value)
 
1085
{
 
1086
        Bonobo_PropertyBag pb;
 
1087
        CORBA_Environment ev;
 
1088
 
 
1089
        CORBA_exception_init (&ev);
 
1090
 
 
1091
        pb = GNOME_Rhythmbox_getPlayerProperties (bonobo->priv->remote, &ev);
 
1092
 
 
1093
        bonobo_pbclient_set_boolean (pb,
 
1094
                                     property,
 
1095
                                     value,
 
1096
                                     &ev);
 
1097
        bonobo_object_release_unref ((Bonobo_Unknown)pb, &ev);
 
1098
}
 
1099
 
 
1100
static void
 
1101
rb_remote_bonobo_client_toggle_visibility_impl (RBRemoteClientProxy *proxy)
 
1102
{
 
1103
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1104
        _rb_remote_bonobo_client_toggle_property (bonobo, "visibility");
 
1105
}
 
1106
 
 
1107
static gboolean 
 
1108
rb_remote_bonobo_client_get_visibility_impl (RBRemoteClientProxy *proxy)
 
1109
{
 
1110
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1111
        return _rb_remote_bonobo_client_get_boolean_property (bonobo, "visibility");
 
1112
}
 
1113
 
 
1114
static void
 
1115
rb_remote_bonobo_client_set_visibility_impl (RBRemoteClientProxy *proxy,
 
1116
                                             gboolean visible)
 
1117
{
 
1118
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1119
        _rb_remote_bonobo_client_set_boolean_property (bonobo, "visibility", visible);
 
1120
}
 
1121
 
 
1122
 
 
1123
static void
 
1124
rb_remote_bonobo_client_toggle_shuffle_impl (RBRemoteClientProxy *proxy)
 
1125
{
 
1126
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1127
        _rb_remote_bonobo_client_toggle_property (bonobo, "shuffle");
 
1128
}
 
1129
 
 
1130
static gboolean 
 
1131
rb_remote_bonobo_client_get_shuffle_impl (RBRemoteClientProxy *proxy)
 
1132
{
 
1133
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1134
        return _rb_remote_bonobo_client_get_boolean_property (bonobo, "shuffle");
 
1135
}
 
1136
 
 
1137
static void
 
1138
rb_remote_bonobo_client_set_shuffle_impl (RBRemoteClientProxy *proxy,
 
1139
                                          gboolean shuffle)
 
1140
{
 
1141
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1142
        _rb_remote_bonobo_client_set_boolean_property (bonobo, "shuffle", shuffle);
 
1143
}
 
1144
 
 
1145
static void
 
1146
rb_remote_bonobo_client_toggle_repeat_impl (RBRemoteClientProxy *proxy)
 
1147
{
 
1148
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1149
        _rb_remote_bonobo_client_toggle_property (bonobo, "repeat");
 
1150
}
 
1151
 
 
1152
static gboolean 
 
1153
rb_remote_bonobo_client_get_repeat_impl (RBRemoteClientProxy *proxy)
 
1154
{
 
1155
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1156
        return _rb_remote_bonobo_client_get_boolean_property (bonobo, "repeat");
 
1157
}
 
1158
 
 
1159
static void
 
1160
rb_remote_bonobo_client_set_repeat_impl (RBRemoteClientProxy *proxy,
 
1161
                                         gboolean repeat)
 
1162
{
 
1163
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1164
        _rb_remote_bonobo_client_set_boolean_property (bonobo, "repeat", repeat);
 
1165
}
 
1166
 
 
1167
 
 
1168
static void
 
1169
rb_remote_bonobo_client_toggle_playing_impl (RBRemoteClientProxy *proxy)
 
1170
{
 
1171
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1172
        CORBA_Environment ev;
 
1173
 
 
1174
        CORBA_exception_init (&ev);
 
1175
        GNOME_Rhythmbox_playPause (bonobo->priv->remote, &ev);
 
1176
        CORBA_exception_free (&ev);
 
1177
}
 
1178
 
 
1179
static void
 
1180
_rb_remote_bonobo_client_set_playing (RBRemoteClientProxy *proxy, gboolean play)
 
1181
{
 
1182
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1183
        gboolean is_playing;
 
1184
        CORBA_Environment ev;
 
1185
 
 
1186
        is_playing = _rb_remote_bonobo_client_get_boolean_property (bonobo, "playing");
 
1187
        
 
1188
        if (is_playing != play) {
 
1189
                CORBA_exception_init (&ev);
 
1190
                rb_remote_bonobo_client_toggle_playing_impl (proxy);
 
1191
                CORBA_exception_free (&ev);
 
1192
        }
 
1193
 
 
1194
}
 
1195
 
 
1196
static void
 
1197
rb_remote_bonobo_client_play_impl (RBRemoteClientProxy *proxy)
 
1198
{
 
1199
        _rb_remote_bonobo_client_set_playing (proxy, TRUE);
 
1200
}
 
1201
 
 
1202
static void
 
1203
rb_remote_bonobo_client_pause_impl (RBRemoteClientProxy *proxy)
 
1204
{
 
1205
        _rb_remote_bonobo_client_set_playing (proxy, FALSE);
 
1206
}
 
1207
 
 
1208
static long
 
1209
rb_remote_bonobo_client_get_playing_time_impl (RBRemoteClientProxy *proxy)
 
1210
{
 
1211
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1212
        CORBA_Environment ev;
 
1213
        long ret;
 
1214
 
 
1215
        CORBA_exception_init (&ev);
 
1216
 
 
1217
        ret = GNOME_Rhythmbox_getPlayingTime (bonobo->priv->remote, &ev);
 
1218
        if (BONOBO_EX (&ev))
 
1219
                ret = -1;
 
1220
 
 
1221
        CORBA_exception_free (&ev);
 
1222
 
 
1223
        return ret;
 
1224
}
 
1225
 
 
1226
static void
 
1227
rb_remote_bonobo_client_set_playing_time_impl (RBRemoteClientProxy *proxy, long time)
 
1228
{
 
1229
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1230
        CORBA_Environment ev;
 
1231
 
 
1232
        CORBA_exception_init (&ev);
 
1233
        GNOME_Rhythmbox_setPlayingTime (bonobo->priv->remote, time, &ev);
 
1234
        CORBA_exception_free (&ev);
 
1235
}
 
1236
 
 
1237
static void
 
1238
rb_remote_bonobo_client_jump_next_impl (RBRemoteClientProxy *proxy)
 
1239
{
 
1240
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1241
        CORBA_Environment ev;
 
1242
 
 
1243
        CORBA_exception_init (&ev);
 
1244
        GNOME_Rhythmbox_next (bonobo->priv->remote, &ev);
 
1245
        CORBA_exception_free (&ev);
 
1246
}
 
1247
 
 
1248
static void
 
1249
rb_remote_bonobo_client_jump_previous_impl (RBRemoteClientProxy *proxy)
 
1250
{
 
1251
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1252
        CORBA_Environment ev;
 
1253
 
 
1254
        CORBA_exception_init (&ev);
 
1255
        GNOME_Rhythmbox_previous (bonobo->priv->remote, &ev);
 
1256
        CORBA_exception_free (&ev);
 
1257
}
 
1258
 
 
1259
 
 
1260
static void
 
1261
rb_remote_bonobo_client_quit_impl (RBRemoteClientProxy *proxy)
 
1262
{
 
1263
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1264
        CORBA_Environment ev;
 
1265
 
 
1266
        CORBA_exception_init (&ev);
 
1267
        GNOME_Rhythmbox_quit (bonobo->priv->remote, &ev);
 
1268
        CORBA_exception_free (&ev);
 
1269
}
 
1270
 
 
1271
static void
 
1272
rb_remote_bonobo_client_set_rating_impl (RBRemoteClientProxy *proxy, double rating)
 
1273
{
 
1274
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1275
        CORBA_Environment ev;
 
1276
 
 
1277
        CORBA_exception_init (&ev);
 
1278
        GNOME_Rhythmbox_setRating (bonobo->priv->remote, rating, &ev);
 
1279
        CORBA_exception_free (&ev);
 
1280
}
 
1281
 
 
1282
static void
 
1283
rb_remote_bonobo_client_seek_impl (RBRemoteClientProxy *proxy, long offset)
 
1284
{
 
1285
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1286
        CORBA_Environment ev;
 
1287
 
 
1288
        CORBA_exception_init (&ev);
 
1289
        GNOME_Rhythmbox_skip (bonobo->priv->remote, offset, &ev);
 
1290
        CORBA_exception_free (&ev);
 
1291
}
 
1292
 
 
1293
static void
 
1294
rb_remote_bonobo_client_set_volume_impl (RBRemoteClientProxy *proxy, float volume)
 
1295
{
 
1296
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1297
        Bonobo_PropertyBag pb;
 
1298
        CORBA_Environment ev;
 
1299
 
 
1300
        CORBA_exception_init (&ev);
 
1301
 
 
1302
        pb = GNOME_Rhythmbox_getPlayerProperties (bonobo->priv->remote, &ev);
 
1303
 
 
1304
        bonobo_pbclient_set_float (pb,
 
1305
                                   "volume",
 
1306
                                   volume,
 
1307
                                   &ev);
 
1308
        bonobo_object_release_unref ((Bonobo_Unknown)pb, &ev);
 
1309
}
 
1310
 
 
1311
static float 
 
1312
rb_remote_bonobo_client_get_volume_impl (RBRemoteClientProxy *proxy)
 
1313
{
 
1314
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1315
        Bonobo_PropertyBag pb;
 
1316
        CORBA_Environment ev;
 
1317
        float v = 1.0f;
 
1318
 
 
1319
        CORBA_exception_init (&ev);
 
1320
 
 
1321
        pb = GNOME_Rhythmbox_getPlayerProperties (bonobo->priv->remote, &ev);
 
1322
 
 
1323
        v = bonobo_pbclient_get_float (pb,
 
1324
                                       "volume",
 
1325
                                       &ev);
 
1326
        bonobo_object_release_unref ((Bonobo_Unknown)pb, &ev);
 
1327
        CORBA_exception_free (&ev);
 
1328
 
 
1329
        return v;
 
1330
}
 
1331
 
 
1332
static void
 
1333
rb_remote_bonobo_client_toggle_mute_impl (RBRemoteClientProxy *proxy)
 
1334
{
 
1335
        RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
 
1336
        CORBA_Environment ev;
 
1337
 
 
1338
        CORBA_exception_init (&ev);
 
1339
        GNOME_Rhythmbox_toggleMute (bonobo->priv->remote, &ev);
 
1340
        CORBA_exception_free (&ev);
 
1341
}
 
1342
 
 
1343