~mniess/ubuntu/trusty/totem/fix-lp1292262

« back to all changes in this revision

Viewing changes to src/plugins/bemused/totem-bemused.c

  • Committer: Bazaar Package Importer
  • Author(s): Raphaël Hertzog
  • Date: 2011-04-10 18:12:25 UTC
  • mfrom: (1.1.14 upstream)
  • mto: (1.5.7 upstream)
  • mto: This revision was merged to the branch mainline in revision 19.
  • Revision ID: james.westby@ubuntu.com-20110410181225-u3x8yhsscjoe8ony
Tags: upstream-3.0.0
Import upstream version 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
#include <bluetooth/sdp_lib.h>
46
46
 
47
47
//FIXME we shouldn't use the video widget directly
48
 
#include "bacon-video-widget.h"
 
48
#include "backend/bacon-video-widget.h"
49
49
#include "totem-plugin.h"
50
50
#include "totem.h"
51
51
 
56
56
#define TOTEM_IS_BEMUSED_PLUGIN_CLASS(k)        (G_TYPE_CHECK_CLASS_TYPE ((k), TOTEM_TYPE_BEMUSED_PLUGIN))
57
57
#define TOTEM_BEMUSED_PLUGIN_GET_CLASS(o)       (G_TYPE_INSTANCE_GET_CLASS ((o), TOTEM_TYPE_BEMUSED_PLUGIN, TotemBemusedPluginClass))
58
58
 
59
 
typedef struct
60
 
{
61
 
        TotemPlugin   parent;
62
 
 
 
59
typedef struct {
63
60
        TotemObject *totem;
64
61
        BaconVideoWidget *bvw;
65
62
        guint server_watch_id;
66
63
        guint client_watch_id;
67
64
        GIOChannel *server_iochan, *client_iochan;
68
65
        sdp_session_t *sdp_session;
69
 
} TotemBemusedPlugin;
70
 
 
71
 
typedef struct
72
 
{
73
 
        TotemPluginClass parent_class;
74
 
} TotemBemusedPluginClass;
75
 
 
76
 
G_MODULE_EXPORT GType register_totem_plugin             (GTypeModule *module);
77
 
GType   totem_bemused_plugin_get_type           (void) G_GNUC_CONST;
78
 
 
79
 
static void totem_bemused_plugin_init           (TotemBemusedPlugin *plugin);
80
 
static void totem_bemused_plugin_finalize               (GObject *object);
81
 
static gboolean impl_activate                           (TotemPlugin *plugin, TotemObject *totem, GError **error);
82
 
static void impl_deactivate                             (TotemPlugin *plugin, TotemObject *totem);
83
 
 
84
 
TOTEM_PLUGIN_REGISTER(TotemBemusedPlugin, totem_bemused_plugin)
 
66
} TotemBemusedPluginPrivate;
 
67
 
 
68
TOTEM_PLUGIN_REGISTER(TOTEM_TYPE_BEMUSED_PLUGIN, TotemBemusedPlugin, totem_bemused_plugin)
85
69
 
86
70
/* Bluetooth functions */
87
71
 
99
83
}
100
84
 
101
85
static void
102
 
send_response_flush (TotemBemusedPlugin *tp, GIOChannel *source, const char *resp, gssize len, gboolean flush)
 
86
send_response_flush (TotemBemusedPlugin *tp, GIOChannel *source, const char *resp, gsize len, gboolean flush)
103
87
{
104
88
        GError *error = NULL;
105
89
        gsize written = 0;
113
97
                flush_response (tp, source);
114
98
 
115
99
        if (len != written)
116
 
                g_message ("sent response: %d chars but len %d chars", (int) written, (int) len);
 
100
                g_message ("sent response: %"G_GSIZE_FORMAT" chars but len %"G_GSIZE_FORMAT" chars", written, len);
117
101
}
118
102
 
119
103
static void
120
 
send_response (TotemBemusedPlugin *tp, GIOChannel *source, const char *resp, gssize len)
 
104
send_response (TotemBemusedPlugin *tp, GIOChannel *source, const char *resp, gsize len)
121
105
{
122
106
        send_response_flush (tp, source, resp, len, TRUE);
123
107
}
124
108
 
125
109
static void
126
 
read_response (TotemBemusedPlugin *tp, GIOChannel *source, char *buf, gssize len)
 
110
read_response (TotemBemusedPlugin *tp, GIOChannel *source, char *buf, gsize len)
127
111
{
128
112
        GError *error = NULL;
129
 
        gsize read;
 
113
        gsize num_read;
130
114
 
131
 
        if (g_io_channel_read_chars (source, buf, len, &read, &error) != G_IO_STATUS_NORMAL) {
 
115
        if (g_io_channel_read_chars (source, buf, len, &num_read, &error) != G_IO_STATUS_NORMAL) {
132
116
                g_message ("error reading response: %s", error->message);
133
117
                g_error_free (error);
134
 
        } else if (len != read) {
135
 
                g_message ("read %d chars but len %d chars", (int) read, (int) len);
 
118
        } else if (len != num_read) {
 
119
                g_message ("read %"G_GSIZE_FORMAT" chars but len %"G_GSIZE_FORMAT" chars", num_read, len);
136
120
        }
137
121
}
138
122
 
140
124
read_filename (TotemBemusedPlugin *tp, GIOChannel *source)
141
125
{
142
126
        char namelenbuf[2], *filename;
143
 
        int namelen;
 
127
        guint namelen;
144
128
 
145
129
        /* Read length */
146
130
        read_response (tp, source, namelenbuf, 2);
159
143
static void
160
144
write_playlist (TotemBemusedPlugin *tp, GIOChannel *source)
161
145
{
 
146
        TotemBemusedPluginPrivate *priv = tp->priv;
162
147
        char buf[11];
163
148
        int playlist_pos, playlist_len, i;
164
149
 
165
 
        playlist_pos = totem_get_playlist_pos (tp->totem);
166
 
        playlist_len = totem_get_playlist_length (tp->totem);
 
150
        playlist_pos = totem_get_playlist_pos (priv->totem);
 
151
        playlist_len = totem_get_playlist_length (priv->totem);
167
152
 
168
153
        strncpy(buf, "PLSTACK", strlen ("PLSTACK"));
169
154
        if (playlist_len == 0) {
180
165
        for (i = 0; i < playlist_len; i++) {
181
166
                char *title;
182
167
 
183
 
                title = totem_get_title_at_playlist_pos (tp->totem, i);
184
 
                if (title == NULL)
 
168
                title = totem_get_title_at_playlist_pos (priv->totem, i);
 
169
                if (title == NULL) {
 
170
                        /* Translators: the parameter is a number used to identify this playlist entry */
185
171
                        title = g_strdup_printf (_("Untitled %d"), i);
 
172
                }
186
173
                g_message ("pushing entry %s", title);
187
174
                send_response_flush (tp, source, title, strlen (title), FALSE);
188
175
                g_free (title);
199
186
        char buf[8];
200
187
 
201
188
        strncpy(buf, "GVOLACK", strlen ("GVOLACK"));
202
 
        volume = bacon_video_widget_get_volume (tp->bvw);
 
189
        volume = bacon_video_widget_get_volume (tp->priv->bvw);
203
190
        if (volume >= 1.0)
204
191
                buf[7] = (unsigned char) 255;
205
192
        else
215
202
 
216
203
        read_response (tp, source, &buf, 1);
217
204
        volume = (double) buf / (double) 256;
218
 
        bacon_video_widget_set_volume (tp->bvw, volume);
 
205
        bacon_video_widget_set_volume (tp->priv->bvw, volume);
219
206
}
220
207
 
221
208
static void
236
223
        char buf;
237
224
 
238
225
        read_response (tp, source, &buf, 1);
239
 
        totem_action_remote_set_setting (tp->totem, setting, buf != 0);
 
226
        totem_action_remote_set_setting (tp->priv->totem, setting, buf != 0);
240
227
}
241
228
 
242
229
static void
243
230
seek_to_pos (TotemBemusedPlugin *tp, GIOChannel *source)
244
231
{
245
232
        char buf[4];
246
 
        int time;
 
233
        int _time;
247
234
 
248
235
        read_response (tp, source, buf, 4);
249
 
        time = buf[0] << 24;
250
 
        time += buf[1] << 16;
251
 
        time += buf[2] << 8;
252
 
        time += buf[3];
 
236
        _time = buf[0] << 24;
 
237
        _time += buf[1] << 16;
 
238
        _time += buf[2] << 8;
 
239
        _time += buf[3];
253
240
 
254
 
        totem_action_seek_time (tp->totem, (gint64) time * 1000);
 
241
        totem_action_seek_time (tp->priv->totem, (gint64) _time * 1000, FALSE);
255
242
}
256
243
 
257
244
static void
260
247
        char buf[2];
261
248
        int len;
262
249
 
263
 
        len = totem_get_playlist_length (tp->totem);
 
250
        len = totem_get_playlist_length (tp->priv->totem);
264
251
 
265
252
        buf[0] = (len >> 8) & 0xFF;
266
253
        buf[1] = len & 0xFF;
354
341
static void
355
342
write_song_info (TotemBemusedPlugin *tp, GIOChannel *source, gboolean send_null)
356
343
{
 
344
        TotemBemusedPluginPrivate *priv = tp->priv;
357
345
        char *title;
358
346
        char status;
359
347
 
363
351
                send_response_flush (tp, source, "INFOACK", strlen ("INFOACK"), FALSE);
364
352
        else
365
353
                send_response_flush (tp, source, "INF2ACK", strlen ("INF2ACK"), FALSE);
366
 
        if (totem_is_playing (tp->totem) != FALSE)
 
354
        if (totem_is_playing (priv->totem) != FALSE)
367
355
                status = 1;
368
 
        else if (totem_is_paused (tp->totem) != FALSE)
 
356
        else if (totem_is_paused (priv->totem) != FALSE)
369
357
                status = 2;
370
358
        else
371
359
                status = 0;
372
360
 
373
361
        send_response_flush (tp, source, &status, 1, FALSE);
374
 
        STUFF4((int) bacon_video_widget_get_stream_length (tp->bvw) / 1000);
375
 
        STUFF4((int) bacon_video_widget_get_current_time (tp->bvw) / 1000);
376
 
        status = totem_action_remote_get_setting (tp->totem, TOTEM_REMOTE_SETTING_SHUFFLE);
 
362
        STUFF4((int) bacon_video_widget_get_stream_length (priv->bvw) / 1000);
 
363
        STUFF4((int) bacon_video_widget_get_current_time (priv->bvw) / 1000);
 
364
        status = totem_action_remote_get_setting (priv->totem, TOTEM_REMOTE_SETTING_SHUFFLE);
377
365
        send_response_flush (tp, source, &status, 1, FALSE);
378
 
        status = totem_action_remote_get_setting (tp->totem, TOTEM_REMOTE_SETTING_REPEAT);
 
366
        status = totem_action_remote_get_setting (priv->totem, TOTEM_REMOTE_SETTING_REPEAT);
379
367
        send_response_flush (tp, source, &status, 1, FALSE);
380
368
 
381
 
        title = totem_get_short_title (tp->totem);
 
369
        title = totem_get_short_title (priv->totem);
382
370
        g_message ("written info for %s", title);
383
371
        if (title == NULL) {
384
372
                flush_response (tp, source);
396
384
set_playlist_at_pos (TotemBemusedPlugin *tp, GIOChannel *source)
397
385
{
398
386
        char buf[2];
399
 
        int index;
 
387
        int idx;
400
388
 
401
389
        read_response (tp, source, buf, 2);
402
 
        index = (buf[0] << 8) + buf[1];
403
 
        totem_action_set_playlist_index (tp->totem, index);
 
390
        idx = (buf[0] << 8) + buf[1];
 
391
        totem_action_set_playlist_index (tp->priv->totem, idx);
404
392
}
405
393
 
406
394
#if 0
448
436
static void
449
437
handle_command (TotemBemusedPlugin *tp, GIOChannel *source, const char *cmd)
450
438
{
 
439
        TotemBemusedPluginPrivate *priv = tp->priv;
 
440
 
451
441
        g_message ("cmd: %s", cmd);
452
442
 
453
443
        CMD_IS("CHCK") {
461
451
        } else CMD_IS("FADE") {
462
452
                //stop
463
453
        } else CMD_IS("FFWD") {
464
 
                totem_action_remote (tp->totem, TOTEM_REMOTE_COMMAND_SEEK_FORWARD, NULL);
 
454
                totem_action_remote (priv->totem, TOTEM_REMOTE_COMMAND_SEEK_FORWARD, NULL);
465
455
        } else CMD_IS("FINF") {
466
456
                write_detailed_file_info (tp, source);
467
457
        } else CMD_IS("GVOL") {
475
465
        } else CMD_IS("LIST") {
476
466
                write_directory_listing (tp, source, TRUE);
477
467
        } else CMD_IS("NEXT") {
478
 
                totem_action_remote (tp->totem, TOTEM_REMOTE_COMMAND_NEXT, NULL);
 
468
                totem_action_remote (priv->totem, TOTEM_REMOTE_COMMAND_NEXT, NULL);
479
469
        } else CMD_IS("PAUS") {
480
 
                totem_action_remote (tp->totem, TOTEM_REMOTE_COMMAND_PAUSE, NULL);
 
470
                totem_action_remote (priv->totem, TOTEM_REMOTE_COMMAND_PAUSE, NULL);
481
471
        } else CMD_IS("PLAY") {
482
472
                add_or_enqueue (tp, source, TOTEM_REMOTE_COMMAND_REPLACE);
483
473
        } else CMD_IS("PLEN") {
485
475
        } else CMD_IS("PLST") {
486
476
                write_playlist (tp, source);
487
477
        } else CMD_IS("PREV") {
488
 
                totem_action_remote (tp->totem, TOTEM_REMOTE_COMMAND_PREVIOUS, NULL);
 
478
                totem_action_remote (priv->totem, TOTEM_REMOTE_COMMAND_PREVIOUS, NULL);
489
479
        } else CMD_IS("REPT") {
490
480
                set_setting (tp, source, TOTEM_REMOTE_SETTING_REPEAT);
491
481
        } else CMD_IS("RMAL") {
492
 
                totem_action_remote (tp->totem, TOTEM_REMOTE_COMMAND_REPLACE, NULL);
 
482
                totem_action_remote (priv->totem, TOTEM_REMOTE_COMMAND_REPLACE, NULL);
493
483
        } else CMD_IS("RWND") {
494
 
                totem_action_remote (tp->totem, TOTEM_REMOTE_COMMAND_SEEK_BACKWARD, NULL);
 
484
                totem_action_remote (priv->totem, TOTEM_REMOTE_COMMAND_SEEK_BACKWARD, NULL);
495
485
        } else CMD_IS("SHFL") {
496
486
                set_setting (tp, source, TOTEM_REMOTE_SETTING_SHUFFLE);
497
487
        } else CMD_IS("SEEK") {
498
488
                seek_to_pos (tp, source);
499
489
        } else CMD_IS("SHUT") {
500
 
                totem_action_remote (tp->totem, TOTEM_REMOTE_COMMAND_QUIT, NULL);
 
490
                totem_action_remote (priv->totem, TOTEM_REMOTE_COMMAND_QUIT, NULL);
501
491
        } else CMD_IS("STEN") {
502
492
                //stop at end of track
503
493
        } else CMD_IS("SLCT") {
505
495
        } else CMD_IS("STOP") {
506
496
                //stop
507
497
        } else CMD_IS("STRT") {
508
 
                totem_action_remote (tp->totem, TOTEM_REMOTE_COMMAND_PLAY, NULL);
 
498
                totem_action_remote (priv->totem, TOTEM_REMOTE_COMMAND_PLAY, NULL);
509
499
        } else CMD_IS("VOLM") {
510
500
                set_volume (tp, source);
511
501
        } else CMD_IS("VERS") {
525
515
 
526
516
        if (condition & G_IO_IN || condition & G_IO_PRI) {
527
517
                char buf[5];
528
 
                gsize read;
 
518
                gsize num_read;
529
519
 
530
520
                status = G_IO_STATUS_NORMAL;
531
521
 
532
522
                while (status == G_IO_STATUS_NORMAL) {
533
523
                        memset(buf, 0, 5);
534
 
                        status = g_io_channel_read_chars (source, buf, 4, &read, NULL);
 
524
                        status = g_io_channel_read_chars (source, buf, 4, &num_read, NULL);
535
525
 
536
526
                        if (status == G_IO_STATUS_NORMAL)
537
527
                                handle_command (tp, source, buf);
552
542
}
553
543
 
554
544
static gboolean
555
 
server_watch_func (GIOChannel *source, GIOCondition condition, gpointer data)
 
545
server_watch_func (GIOChannel *source, GIOCondition condition, TotemBemusedPlugin *tp)
556
546
{
557
 
        TotemBemusedPlugin *tp = (TotemBemusedPlugin *) data;
 
547
        TotemBemusedPluginPrivate *priv = tp->priv;
558
548
 
559
549
        g_message ("server_watch_func");
560
550
 
579
569
                        //FIXME check batostr(&ba) is our expected client
580
570
                        g_message ("connected from %s", batostr(&ba));
581
571
 
582
 
                        if (tp->bvw != NULL)
583
 
                                g_object_unref (G_OBJECT (tp->bvw));
584
 
                        tp->bvw = BACON_VIDEO_WIDGET (totem_get_video_widget (tp->totem));
 
572
                        if (priv->bvw != NULL)
 
573
                                g_object_unref (G_OBJECT (priv->bvw));
 
574
                        priv->bvw = BACON_VIDEO_WIDGET (totem_get_video_widget (priv->totem));
585
575
 
586
 
                        tp->client_iochan = g_io_channel_unix_new (client_fd);
587
 
                        g_io_channel_set_encoding (tp->client_iochan, NULL, NULL);
588
 
                        g_io_channel_set_buffered (tp->client_iochan, FALSE);
589
 
                        g_io_channel_set_flags (tp->client_iochan,
590
 
                                                g_io_channel_get_flags (tp->client_iochan) | G_IO_FLAG_NONBLOCK,
 
576
                        priv->client_iochan = g_io_channel_unix_new (client_fd);
 
577
                        g_io_channel_set_encoding (priv->client_iochan, NULL, NULL);
 
578
                        g_io_channel_set_buffered (priv->client_iochan, FALSE);
 
579
                        g_io_channel_set_flags (priv->client_iochan,
 
580
                                                g_io_channel_get_flags (priv->client_iochan) | G_IO_FLAG_NONBLOCK,
591
581
                                                NULL);
592
 
                        tp->client_watch_id = g_io_add_watch (tp->client_iochan,
 
582
                        priv->client_watch_id = g_io_add_watch (priv->client_iochan,
593
583
                                                       G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
594
584
                                                       client_watch_func,
595
585
                                                       tp);
596
 
                        g_io_channel_unref (tp->client_iochan);
 
586
                        g_io_channel_unref (priv->client_iochan);
597
587
                }
598
588
        }
599
589
 
684
674
}
685
675
 
686
676
/* Object functions */
687
 
 
688
 
static void
689
 
totem_bemused_plugin_class_init (TotemBemusedPluginClass *klass)
690
 
{
691
 
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
692
 
        TotemPluginClass *plugin_class = TOTEM_PLUGIN_CLASS (klass);
693
 
 
694
 
        object_class->finalize = totem_bemused_plugin_finalize;
695
 
 
696
 
        plugin_class->activate = impl_activate;
697
 
        plugin_class->deactivate = impl_deactivate;
698
 
}
699
 
 
700
 
static void
701
 
totem_bemused_plugin_init (TotemBemusedPlugin *plugin)
702
 
{
703
 
}
704
 
 
705
 
static void
706
 
totem_bemused_plugin_finalize (GObject *object)
707
 
{
708
 
        G_OBJECT_CLASS (totem_bemused_plugin_parent_class)->finalize (object);
709
 
}
710
 
 
711
 
static gboolean
712
 
impl_activate (TotemPlugin *plugin,
713
 
               TotemObject *totem,
714
 
               GError **error)
 
677
static void
 
678
impl_activate (PeasActivatable *plugin)
715
679
{
716
680
        TotemBemusedPlugin *tp = TOTEM_BEMUSED_PLUGIN (plugin);
 
681
        TotemBemusedPluginPrivate *priv = tp->priv;
717
682
        int fd, channel;
718
683
        struct sockaddr_rc addr;
719
684
 
720
 
        tp->totem = totem;
 
685
        priv->totem = g_object_get_data (G_OBJECT (plugin), "object");
721
686
 
722
687
        fd = socket (PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
723
688
        if (fd < 0) {
724
689
                g_message ("couldn't create socket");
725
690
                //FIXME set error
726
 
                return FALSE;
 
691
                return;
727
692
        }
728
693
 
729
694
        g_message ("socket created");
730
695
 
731
696
        channel = 1;
732
 
        tp->sdp_session = sdp_svc_add_spp (channel,
 
697
        priv->sdp_session = sdp_svc_add_spp (channel,
733
698
                                           BEMUSED_SVC_NAME,
734
699
                                           BEMUSED_SVC_DESC,
735
700
                                           BEMUSED_SVC_PROV,
736
701
                                           BEMUSED_SVC_UUID);
737
 
        if (tp->sdp_session == NULL) {
 
702
        if (priv->sdp_session == NULL) {
738
703
                close (fd);
739
704
                g_message ("registering service failed");
740
 
                return FALSE;
 
705
                return;
741
706
        }
742
707
 
743
708
        addr.rc_family = AF_BLUETOOTH;
746
711
 
747
712
        if (bind(fd, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
748
713
                //FIXME
749
 
                sdp_svc_del (tp->sdp_session);
 
714
                sdp_svc_del (priv->sdp_session);
750
715
                g_message ("couldn't bind");
751
 
                return FALSE;
 
716
                return;
752
717
        }
753
718
 
754
719
        g_message ("bind launched");
756
721
        if (listen (fd, 10) < 0) {
757
722
                //FIXME
758
723
                g_message ("couldn't listen");
759
 
                sdp_svc_del (tp->sdp_session);
760
 
                return FALSE;
 
724
                sdp_svc_del (priv->sdp_session);
 
725
                return;
761
726
        }
762
727
 
763
728
        g_message ("listen launched");
764
729
 
765
 
        tp->server_iochan = g_io_channel_unix_new (fd);
766
 
        g_io_channel_set_encoding (tp->server_iochan, NULL, NULL);
767
 
        tp->server_watch_id = g_io_add_watch (tp->server_iochan,
 
730
        priv->server_iochan = g_io_channel_unix_new (fd);
 
731
        g_io_channel_set_encoding (priv->server_iochan, NULL, NULL);
 
732
        priv->server_watch_id = g_io_add_watch (priv->server_iochan,
768
733
                                              G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
769
 
                                              server_watch_func,
 
734
                                              (GIOFunc) server_watch_func,
770
735
                                              plugin);
771
 
        g_io_channel_unref (tp->server_iochan);
 
736
        g_io_channel_unref (priv->server_iochan);
772
737
 
773
738
        g_message ("io chan set");
774
739
 
775
740
        //FIXME
776
 
 
777
 
        return TRUE;
778
741
}
779
742
 
780
743
static void
781
 
impl_deactivate (TotemPlugin *plugin,
782
 
                 TotemObject *totem)
 
744
impl_deactivate (PeasActivatable *plugin)
783
745
{
784
 
        totem_remove_sidebar_page (totem, "sidebar-test");
785
 
        g_message ("Just removed a test sidebar");
 
746
        //FIXME
786
747
}
787
748