2
* arch-tag: Implementation of Rhythmbox Bonobo remoting
4
* Copyright (C) 2004 Colin Walters <walters@gnome.org>
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)
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.
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.
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>
36
#include <libgnome/libgnome.h>
37
#include <libgnome/gnome-i18n.h>
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);
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);
81
static Bonobo_PropertyBag rb_remote_bonobo_corba_get_player_properties (PortableServer_Servant _servant, CORBA_Environment *ev);
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,
89
RBRemoteBonobo *bonobo);
90
static void rb_remote_bonobo_player_notify_cb (GObject *object,
92
RBRemoteBonobo *bonobo);
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);
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);
123
static GObjectClass *parent_class;
135
struct RBRemoteBonoboPrivate
139
GNOME_Rhythmbox remote;
141
RBRemoteProxy *proxy;
143
BonoboPropertyBag *pb;
146
GParamSpec *property_spec[16];
150
rb_remote_bonobo_get_type (void)
152
static GType type = 0;
156
static GTypeInfo info =
158
sizeof (RBRemoteBonoboClass),
161
(GClassInitFunc) rb_remote_bonobo_class_init,
164
sizeof (RBRemoteBonobo),
166
(GInstanceInitFunc) rb_remote_bonobo_init
169
static const GInterfaceInfo rb_remote_client_proxy_info =
171
(GInterfaceInitFunc) rb_remote_bonobo_remote_client_proxy_init,
176
type = bonobo_type_unique (BONOBO_TYPE_OBJECT,
177
POA_GNOME_Rhythmbox__init,
178
POA_GNOME_Rhythmbox__fini,
179
G_STRUCT_OFFSET (RBRemoteBonoboClass, epv),
183
g_type_add_interface_static (type,
184
RB_TYPE_REMOTE_CLIENT_PROXY,
185
&rb_remote_client_proxy_info);
192
rb_remote_bonobo_class_init (RBRemoteBonoboClass *klass)
194
GObjectClass *object_class = (GObjectClass *) klass;
195
POA_GNOME_Rhythmbox__epv *epv = &klass->epv;
197
parent_class = g_type_class_peek_parent (klass);
199
object_class->dispose = rb_remote_bonobo_dispose;
200
object_class->finalize = rb_remote_bonobo_finalize;
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;
220
rb_remote_bonobo_remote_client_proxy_init (RBRemoteClientProxyIface *iface)
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;
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;
254
rb_bonobo_workaround_lock (void)
256
g_static_rec_mutex_lock (&_rb_bonobo_mutex);
260
rb_bonobo_workaround_unlock (void)
262
g_static_rec_mutex_unlock (&_rb_bonobo_mutex);
266
rb_remote_bonobo_preinit (void)
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.
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.
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.
298
if (!set_lock_functions)
300
gdk_threads_set_lock_functions (G_CALLBACK (rb_bonobo_workaround_lock),
301
G_CALLBACK (rb_bonobo_workaround_unlock));
302
set_lock_functions = TRUE;
307
rb_remote_bonobo_init (RBRemoteBonobo *bonobo)
309
bonobo->priv = g_new0 (RBRemoteBonoboPrivate, 1);
313
rb_remote_bonobo_dispose (GObject *object)
315
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (object);
317
if (bonobo->priv->disposed)
319
bonobo->priv->disposed = TRUE;
323
rb_remote_bonobo_finalize (GObject *object)
325
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (object);
327
g_free (bonobo->priv);
329
(* G_OBJECT_CLASS (parent_class)->finalize) (object);
333
rb_remote_bonobo_new (void)
335
return g_object_new (RB_TYPE_REMOTE_BONOBO, NULL, NULL);
340
rb_remote_bonobo_corba_quit (PortableServer_Servant _servant,
341
CORBA_Environment *ev)
343
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
345
GDK_THREADS_ENTER ();
346
rb_remote_proxy_quit (bonobo->priv->proxy);
347
GDK_THREADS_LEAVE ();
351
rb_remote_bonobo_corba_handle_file (PortableServer_Servant _servant,
352
const CORBA_char *uri,
353
CORBA_Environment *ev)
355
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
357
GDK_THREADS_ENTER ();
358
rb_remote_proxy_load_uri (bonobo->priv->proxy, uri, TRUE);
359
GDK_THREADS_LEAVE ();
363
rb_remote_bonobo_corba_add_to_library (PortableServer_Servant _servant,
364
const CORBA_char *uri,
365
CORBA_Environment *ev)
367
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
369
GDK_THREADS_ENTER ();
370
rb_remote_proxy_load_uri (bonobo->priv->proxy, uri, FALSE);
371
GDK_THREADS_LEAVE ();
375
rb_remote_bonobo_corba_grab_focus (PortableServer_Servant _servant,
376
CORBA_Environment *ev)
378
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
380
GDK_THREADS_ENTER ();
381
rb_remote_proxy_grab_focus (bonobo->priv->proxy);
382
GDK_THREADS_LEAVE ();
386
rb_remote_bonobo_corba_playpause (PortableServer_Servant _servant,
387
CORBA_Environment *ev)
389
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
391
GDK_THREADS_ENTER ();
393
if (rb_remote_proxy_playing (bonobo->priv->proxy))
394
rb_remote_proxy_pause (bonobo->priv->proxy);
396
rb_remote_proxy_play (bonobo->priv->proxy);
398
GDK_THREADS_LEAVE ();
402
rb_remote_bonobo_corba_select (PortableServer_Servant _servant,
403
const CORBA_char *uri,
404
CORBA_Environment *ev)
406
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
408
GDK_THREADS_ENTER ();
409
rb_remote_proxy_select_uri (bonobo->priv->proxy, uri);
410
GDK_THREADS_LEAVE ();
414
rb_remote_bonobo_corba_play (PortableServer_Servant _servant,
415
const CORBA_char *uri,
416
CORBA_Environment *ev)
418
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
420
GDK_THREADS_ENTER ();
421
rb_remote_proxy_play_uri (bonobo->priv->proxy, uri);
422
GDK_THREADS_LEAVE ();
426
rb_remote_bonobo_corba_next (PortableServer_Servant _servant,
427
CORBA_Environment *ev)
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 ();
436
rb_remote_bonobo_corba_previous (PortableServer_Servant _servant,
437
CORBA_Environment *ev)
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 ();
446
rb_remote_bonobo_corba_get_playing_time (PortableServer_Servant _servant,
447
CORBA_Environment *ev)
449
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
452
GDK_THREADS_ENTER ();
453
playing_time = rb_remote_proxy_get_playing_time (bonobo->priv->proxy);
454
GDK_THREADS_LEAVE ();
456
return (CORBA_long) playing_time;
460
rb_remote_bonobo_corba_set_playing_time (PortableServer_Servant _servant,
461
CORBA_long time, CORBA_Environment *ev)
463
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
465
GDK_THREADS_ENTER ();
466
rb_remote_proxy_set_playing_time (bonobo->priv->proxy, (long) time);
467
GDK_THREADS_LEAVE ();
471
rb_remote_bonobo_corba_skip (PortableServer_Servant _servant,
472
CORBA_long offset, CORBA_Environment *ev)
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 ();
481
rb_remote_bonobo_corba_set_rating (PortableServer_Servant _servant,
482
CORBA_double rating, CORBA_Environment *ev)
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 ();
491
rb_remote_bonobo_corba_toggle_mute (PortableServer_Servant _servant,
492
CORBA_Environment *ev)
494
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
496
GDK_THREADS_ENTER ();
497
rb_remote_proxy_toggle_mute (bonobo->priv->proxy);
498
GDK_THREADS_LEAVE ();
501
static GNOME_Rhythmbox_SongInfo *
502
convert_from_rb_remote_song (const RBRemoteSong *song)
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;
520
static GNOME_Rhythmbox_SongInfo *
521
get_song_info_from_player (RBRemoteProxy *proxy)
524
RBRemoteSong *song = NULL;
525
GNOME_Rhythmbox_SongInfo *song_info = NULL;
527
GDK_THREADS_ENTER ();
528
uri = rb_remote_proxy_get_playing_uri (proxy);
530
song = g_new0 (RBRemoteSong, 1);
532
if (rb_remote_proxy_get_song_info (proxy, uri, song) == TRUE) {
533
song_info = convert_from_rb_remote_song (song);
535
rb_remote_song_free (song);
538
GDK_THREADS_LEAVE ();
545
bonobo_pb_get_prop (BonoboPropertyBag *bag,
548
CORBA_Environment *ev,
551
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (user_data);
553
if ((arg_id >= PROP_LAST_STATIC) &&
554
(arg_id < (bonobo->priv->next_property + PROP_LAST_STATIC))) {
556
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (user_data);
557
GParamSpec *param = bonobo->priv->property_spec[arg_id - PROP_LAST_STATIC];
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,
564
GDK_THREADS_LEAVE ();
565
bonobo_arg_from_gvalue (arg, &value);
566
g_value_unset (&value);
572
case PROP_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);
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);
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);
604
GNOME_Rhythmbox_SongInfo *ret_val;
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;
611
arg->_type = TC_GNOME_Rhythmbox_SongInfo;
617
bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
623
bonobo_pb_set_prop (BonoboPropertyBag *bag,
624
const BonoboArg *arg,
626
CORBA_Environment *ev,
629
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (user_data);
631
if ((arg_id >= PROP_LAST_STATIC) &&
632
(arg_id < (bonobo->priv->next_property + PROP_LAST_STATIC))) {
634
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (user_data);
635
GParamSpec *param = bonobo->priv->property_spec[arg_id - PROP_LAST_STATIC];
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,
643
GDK_THREADS_LEAVE ();
644
g_value_unset (&value);
650
case PROP_VISIBILITY:
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 ();
660
bonobo_exception_set (ev, ex_Bonobo_PropertyBag_ReadOnly);
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 ();
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 ();
682
bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
688
rb_remote_bonobo_add_player_property (RBRemoteBonobo *bonobo,
689
const gchar *property,
690
const gchar *description)
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,
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)),
710
static Bonobo_PropertyBag
711
rb_remote_bonobo_corba_get_player_properties (PortableServer_Servant _servant,
712
CORBA_Environment *ev)
714
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (bonobo_object (_servant));
716
GDK_THREADS_ENTER ();
717
if (bonobo->priv->pb == NULL) {
718
bonobo->priv->pb = bonobo_property_bag_new (bonobo_pb_get_prop,
723
bonobo_property_bag_add (bonobo->priv->pb, "visibility",
724
PROP_VISIBILITY, BONOBO_ARG_BOOLEAN, NULL,
725
_("Whether the main window is visible"), 0);
727
bonobo_property_bag_add (bonobo->priv->pb, "shuffle",
728
PROP_SHUFFLE, BONOBO_ARG_BOOLEAN, NULL,
729
_("Whether shuffle is enabled"), 0);
731
bonobo_property_bag_add (bonobo->priv->pb, "repeat",
732
PROP_REPEAT, BONOBO_ARG_BOOLEAN, NULL,
733
_("Whether repeat is enabled"), 0);
735
bonobo_property_bag_add (bonobo->priv->pb, "song",
736
PROP_SONG, TC_GNOME_Rhythmbox_SongInfo, NULL,
737
_("Properties for the current song"), 0);
739
rb_remote_proxy_player_notify_handler (bonobo->priv->proxy,
740
G_CALLBACK (rb_remote_bonobo_player_notify_cb),
743
rb_remote_bonobo_add_player_property (bonobo,
745
_("Whether Rhythmbox is currently playing"));
747
rb_remote_bonobo_add_player_property (bonobo,
749
_("What play order to use"));
751
rb_remote_bonobo_add_player_property (bonobo,
753
_("Current playback volume"));
756
GDK_THREADS_LEAVE ();
758
/* If the creation of the property bag failed,
759
* return a corba exception
762
return bonobo_object_dup_ref (BONOBO_OBJREF (bonobo->priv->pb), NULL);
766
rb_remote_bonobo_song_changed_cb (RBRemoteProxy *proxy,
767
const RBRemoteSong *song,
768
RBRemoteBonobo *bonobo)
770
GNOME_Rhythmbox_SongInfo *song_info;
773
if (bonobo->priv->pb == NULL)
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,
787
bonobo_arg_release (arg);
791
rb_remote_bonobo_visibility_changed_cb (RBRemoteProxy *proxy,
793
RBRemoteBonobo *bonobo)
797
if (bonobo->priv->pb == NULL)
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,
808
bonobo_arg_release (arg);
813
rb_remote_bonobo_player_notify_cb (GObject *object,
815
RBRemoteBonobo *bonobo)
819
BonoboArgType arg_type;
821
if (bonobo->priv->pb == NULL)
824
arg_type = bonobo_arg_type_from_gtype (G_PARAM_SPEC_VALUE_TYPE (param));
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,
834
GDK_THREADS_LEAVE ();
835
bonobo_arg_from_gvalue (arg, &value);
836
bonobo_event_source_notify_listeners_full (bonobo->priv->pb->es,
841
g_value_unset (&value);
842
bonobo_arg_release (arg);
846
rb_remote_bonobo_error_quark (void)
848
static GQuark quark = 0;
850
quark = g_quark_from_static_string ("rb_remote_bonobo_error");
856
rb_shell_corba_exception_to_string (CORBA_Environment *ev)
858
g_return_val_if_fail (ev != NULL, NULL);
860
if ((CORBA_exception_id (ev) != NULL) &&
861
(strcmp (CORBA_exception_id (ev), ex_Bonobo_GeneralError) != 0))
862
return bonobo_exception_get_text (ev);
864
const Bonobo_GeneralError *bonobo_general_error;
866
bonobo_general_error = CORBA_exception_value (ev);
867
if (bonobo_general_error != NULL)
868
return g_strdup (bonobo_general_error->description);
875
rb_remote_bonobo_activate (RBRemoteBonobo *bonobo)
877
bonobo->priv->remote =
878
bonobo_activation_activate_from_id (RB_REMOTE_BONOBO_OAFIID,
879
Bonobo_ACTIVATION_FLAG_EXISTING_ONLY,
881
return bonobo->priv->remote != NULL;
885
shell_weak_ref_cb (gpointer data, GObject *objptr)
887
bonobo_object_unref (BONOBO_OBJECT (data));
891
rb_remote_bonobo_acquire (RBRemoteBonobo *bonobo,
892
RBRemoteProxy *proxy,
895
CORBA_Object corba_object;
896
CORBA_Environment ev;
897
gboolean registration_failed;
899
rb_debug ("registering with bonobo");
901
bonobo->priv->proxy = proxy;
902
g_object_weak_ref (G_OBJECT (proxy), shell_weak_ref_cb, bonobo);
904
g_signal_connect_object (G_OBJECT (proxy),
906
G_CALLBACK (rb_remote_bonobo_song_changed_cb),
909
g_signal_connect_object (G_OBJECT (proxy),
910
"visibility_changed",
911
G_CALLBACK (rb_remote_bonobo_visibility_changed_cb),
915
corba_object = bonobo_object_corba_objref (BONOBO_OBJECT (bonobo));
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;
921
if (bonobo_activation_active_server_register (RB_FACTORY_OAFIID, corba_object) != Bonobo_ACTIVATION_REG_SUCCESS)
922
registration_failed = TRUE;
924
CORBA_exception_init (&ev);
926
if (registration_failed) {
927
char *msg = rb_shell_corba_exception_to_string (&ev);
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);
936
rb_debug ("failed to register with bonobo activation");
938
rb_debug ("successfully registered with bonobo activation");
940
CORBA_exception_free (&ev);
942
return !registration_failed;
948
rb_remote_bonobo_client_handle_uri_impl (RBRemoteClientProxy *proxy, const char *uri)
950
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
951
CORBA_Environment ev;
953
CORBA_exception_init (&ev);
954
GNOME_Rhythmbox_handleFile (bonobo->priv->remote, uri, &ev);
955
CORBA_exception_free (&ev);
958
static RBRemoteSong *
959
rb_remote_bonobo_client_get_playing_song_impl (RBRemoteClientProxy *proxy)
961
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
962
RBRemoteSong *song = NULL;
963
Bonobo_PropertyBag pb;
965
CORBA_Environment ev;
966
GNOME_Rhythmbox_SongInfo *song_info = NULL;
969
* Yes, this is insane.
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);
980
any = bonobo_pbclient_get_value (pb, "song",
981
TC_GNOME_Rhythmbox_SongInfo,
983
if (BONOBO_EX (&ev)) {
984
char *err = bonobo_exception_get_text (&ev);
985
g_warning (_("An exception occured '%s'"), err);
987
bonobo_object_release_unref ((Bonobo_Unknown) pb, &ev);
991
if ((any == NULL) || (!CORBA_TypeCode_equivalent (any->_type, TC_GNOME_Rhythmbox_SongInfo, NULL))) {
994
song_info = (GNOME_Rhythmbox_SongInfo*)any->_value;
995
any->_release = FALSE;
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;
1014
CORBA_free (song_info);
1017
bonobo_object_release_unref ((Bonobo_Unknown) pb, &ev);
1023
rb_remote_bonobo_client_grab_focus_impl (RBRemoteClientProxy *proxy)
1025
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1026
CORBA_Environment ev;
1028
CORBA_exception_init (&ev);
1029
GNOME_Rhythmbox_grabFocus (bonobo->priv->remote, &ev);
1030
CORBA_exception_free (&ev);
1034
_rb_remote_bonobo_client_toggle_property (RBRemoteBonobo *bonobo,
1035
const char *property)
1037
Bonobo_PropertyBag pb;
1039
CORBA_Environment ev;
1041
CORBA_exception_init (&ev);
1043
pb = GNOME_Rhythmbox_getPlayerProperties (bonobo->priv->remote, &ev);
1045
v = bonobo_pbclient_get_boolean (pb,
1048
if (BONOBO_EX (&ev)) {
1052
bonobo_pbclient_set_boolean (pb,
1056
if (BONOBO_EX (&ev))
1059
bonobo_object_release_unref ((Bonobo_Unknown)pb, &ev);
1063
_rb_remote_bonobo_client_get_boolean_property (RBRemoteBonobo *bonobo,
1064
const char *property)
1066
Bonobo_PropertyBag pb;
1068
CORBA_Environment ev;
1070
CORBA_exception_init (&ev);
1072
pb = GNOME_Rhythmbox_getPlayerProperties (bonobo->priv->remote, &ev);
1074
v = bonobo_pbclient_get_boolean (pb,
1077
bonobo_object_release_unref ((Bonobo_Unknown)pb, &ev);
1082
_rb_remote_bonobo_client_set_boolean_property (RBRemoteBonobo *bonobo,
1083
const char *property,
1086
Bonobo_PropertyBag pb;
1087
CORBA_Environment ev;
1089
CORBA_exception_init (&ev);
1091
pb = GNOME_Rhythmbox_getPlayerProperties (bonobo->priv->remote, &ev);
1093
bonobo_pbclient_set_boolean (pb,
1097
bonobo_object_release_unref ((Bonobo_Unknown)pb, &ev);
1101
rb_remote_bonobo_client_toggle_visibility_impl (RBRemoteClientProxy *proxy)
1103
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1104
_rb_remote_bonobo_client_toggle_property (bonobo, "visibility");
1108
rb_remote_bonobo_client_get_visibility_impl (RBRemoteClientProxy *proxy)
1110
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1111
return _rb_remote_bonobo_client_get_boolean_property (bonobo, "visibility");
1115
rb_remote_bonobo_client_set_visibility_impl (RBRemoteClientProxy *proxy,
1118
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1119
_rb_remote_bonobo_client_set_boolean_property (bonobo, "visibility", visible);
1124
rb_remote_bonobo_client_toggle_shuffle_impl (RBRemoteClientProxy *proxy)
1126
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1127
_rb_remote_bonobo_client_toggle_property (bonobo, "shuffle");
1131
rb_remote_bonobo_client_get_shuffle_impl (RBRemoteClientProxy *proxy)
1133
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1134
return _rb_remote_bonobo_client_get_boolean_property (bonobo, "shuffle");
1138
rb_remote_bonobo_client_set_shuffle_impl (RBRemoteClientProxy *proxy,
1141
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1142
_rb_remote_bonobo_client_set_boolean_property (bonobo, "shuffle", shuffle);
1146
rb_remote_bonobo_client_toggle_repeat_impl (RBRemoteClientProxy *proxy)
1148
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1149
_rb_remote_bonobo_client_toggle_property (bonobo, "repeat");
1153
rb_remote_bonobo_client_get_repeat_impl (RBRemoteClientProxy *proxy)
1155
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1156
return _rb_remote_bonobo_client_get_boolean_property (bonobo, "repeat");
1160
rb_remote_bonobo_client_set_repeat_impl (RBRemoteClientProxy *proxy,
1163
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1164
_rb_remote_bonobo_client_set_boolean_property (bonobo, "repeat", repeat);
1169
rb_remote_bonobo_client_toggle_playing_impl (RBRemoteClientProxy *proxy)
1171
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1172
CORBA_Environment ev;
1174
CORBA_exception_init (&ev);
1175
GNOME_Rhythmbox_playPause (bonobo->priv->remote, &ev);
1176
CORBA_exception_free (&ev);
1180
_rb_remote_bonobo_client_set_playing (RBRemoteClientProxy *proxy, gboolean play)
1182
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1183
gboolean is_playing;
1184
CORBA_Environment ev;
1186
is_playing = _rb_remote_bonobo_client_get_boolean_property (bonobo, "playing");
1188
if (is_playing != play) {
1189
CORBA_exception_init (&ev);
1190
rb_remote_bonobo_client_toggle_playing_impl (proxy);
1191
CORBA_exception_free (&ev);
1197
rb_remote_bonobo_client_play_impl (RBRemoteClientProxy *proxy)
1199
_rb_remote_bonobo_client_set_playing (proxy, TRUE);
1203
rb_remote_bonobo_client_pause_impl (RBRemoteClientProxy *proxy)
1205
_rb_remote_bonobo_client_set_playing (proxy, FALSE);
1209
rb_remote_bonobo_client_get_playing_time_impl (RBRemoteClientProxy *proxy)
1211
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1212
CORBA_Environment ev;
1215
CORBA_exception_init (&ev);
1217
ret = GNOME_Rhythmbox_getPlayingTime (bonobo->priv->remote, &ev);
1218
if (BONOBO_EX (&ev))
1221
CORBA_exception_free (&ev);
1227
rb_remote_bonobo_client_set_playing_time_impl (RBRemoteClientProxy *proxy, long time)
1229
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1230
CORBA_Environment ev;
1232
CORBA_exception_init (&ev);
1233
GNOME_Rhythmbox_setPlayingTime (bonobo->priv->remote, time, &ev);
1234
CORBA_exception_free (&ev);
1238
rb_remote_bonobo_client_jump_next_impl (RBRemoteClientProxy *proxy)
1240
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1241
CORBA_Environment ev;
1243
CORBA_exception_init (&ev);
1244
GNOME_Rhythmbox_next (bonobo->priv->remote, &ev);
1245
CORBA_exception_free (&ev);
1249
rb_remote_bonobo_client_jump_previous_impl (RBRemoteClientProxy *proxy)
1251
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1252
CORBA_Environment ev;
1254
CORBA_exception_init (&ev);
1255
GNOME_Rhythmbox_previous (bonobo->priv->remote, &ev);
1256
CORBA_exception_free (&ev);
1261
rb_remote_bonobo_client_quit_impl (RBRemoteClientProxy *proxy)
1263
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1264
CORBA_Environment ev;
1266
CORBA_exception_init (&ev);
1267
GNOME_Rhythmbox_quit (bonobo->priv->remote, &ev);
1268
CORBA_exception_free (&ev);
1272
rb_remote_bonobo_client_set_rating_impl (RBRemoteClientProxy *proxy, double rating)
1274
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1275
CORBA_Environment ev;
1277
CORBA_exception_init (&ev);
1278
GNOME_Rhythmbox_setRating (bonobo->priv->remote, rating, &ev);
1279
CORBA_exception_free (&ev);
1283
rb_remote_bonobo_client_seek_impl (RBRemoteClientProxy *proxy, long offset)
1285
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1286
CORBA_Environment ev;
1288
CORBA_exception_init (&ev);
1289
GNOME_Rhythmbox_skip (bonobo->priv->remote, offset, &ev);
1290
CORBA_exception_free (&ev);
1294
rb_remote_bonobo_client_set_volume_impl (RBRemoteClientProxy *proxy, float volume)
1296
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1297
Bonobo_PropertyBag pb;
1298
CORBA_Environment ev;
1300
CORBA_exception_init (&ev);
1302
pb = GNOME_Rhythmbox_getPlayerProperties (bonobo->priv->remote, &ev);
1304
bonobo_pbclient_set_float (pb,
1308
bonobo_object_release_unref ((Bonobo_Unknown)pb, &ev);
1312
rb_remote_bonobo_client_get_volume_impl (RBRemoteClientProxy *proxy)
1314
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1315
Bonobo_PropertyBag pb;
1316
CORBA_Environment ev;
1319
CORBA_exception_init (&ev);
1321
pb = GNOME_Rhythmbox_getPlayerProperties (bonobo->priv->remote, &ev);
1323
v = bonobo_pbclient_get_float (pb,
1326
bonobo_object_release_unref ((Bonobo_Unknown)pb, &ev);
1327
CORBA_exception_free (&ev);
1333
rb_remote_bonobo_client_toggle_mute_impl (RBRemoteClientProxy *proxy)
1335
RBRemoteBonobo *bonobo = RB_REMOTE_BONOBO (proxy);
1336
CORBA_Environment ev;
1338
CORBA_exception_init (&ev);
1339
GNOME_Rhythmbox_toggleMute (bonobo->priv->remote, &ev);
1340
CORBA_exception_free (&ev);