Update changelog
[profile/ivi/rygel-gst-0-10-fullscreen-renderer.git] / src / rygel-playbin-player.c
1 /*
2  * Copyright (C) 2008 OpenedHand Ltd.
3  * Copyright (C) 2009,2010,2011,2012 Nokia Corporation.
4  * Copyright (C) 2012 Openismus GmbH
5  * Copyright (C) 2012 Intel Corporation.
6  *
7  * Author: Jorn Baayen <jorn@openedhand.com>
8  *         Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
9  *                               <zeeshan.ali@nokia.com>
10  *         Jens Georg <jensg@openismus.com>
11  *
12  * Rygel is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Lesser General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * Rygel is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25  */
26
27 #include "rygel-playbin-player.h"
28 #include <libgupnp-av/gupnp-av.h>
29 #include <rygel-renderer.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 static void rygel_playbin_player_rygel_media_player_interface_init (RygelMediaPlayerIface *iface);
34
35 /**
36  * Implementation of RygelMediaPlayer for GStreamer.
37  *
38  * This class is useful only when implementing Rygel plugins.
39  */
40
41 G_DEFINE_TYPE_WITH_CODE (RygelPlaybinPlayer,
42                          rygel_playbin_player,
43                          G_TYPE_OBJECT,
44                          G_IMPLEMENT_INTERFACE (RYGEL_TYPE_MEDIA_PLAYER,
45                                                 rygel_playbin_player_rygel_media_player_interface_init))
46
47 #define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
48
49 struct _RygelPlaybinPlayerPrivate {
50   gboolean duration_hint;
51   gboolean is_live;
52   gboolean foreign;
53   gboolean buffering;
54   GstElement *_playbin;
55   gchar *_playback_state;
56   gchar **_allowed_playback_speeds;
57   gint _allowed_playback_speeds_length;
58   gint __allowed_playback_speeds_size_;
59   gchar *_playback_speed;
60   gchar *transfer_mode;
61   gboolean uri_update_hint;
62   gchar *_uri;
63   gchar *_mime_type;
64   gchar *_metadata;
65   gchar *_content_features;
66   GUPnPProtocolInfo *protocol_info;
67 };
68
69 static RygelMediaPlayerIface* rygel_playbin_player_rygel_media_player_parent_iface = NULL;
70
71 #define RYGEL_PLAYBIN_PLAYER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RYGEL_TYPE_PLAYBIN_PLAYER, RygelPlaybinPlayerPrivate))
72 enum  {
73   RYGEL_PLAYBIN_PLAYER_DUMMY_PROPERTY,
74   RYGEL_PLAYBIN_PLAYER_PLAYBIN,
75   RYGEL_PLAYBIN_PLAYER_PLAYBACK_STATE,
76   RYGEL_PLAYBIN_PLAYER_ALLOWED_PLAYBACK_SPEEDS,
77   RYGEL_PLAYBIN_PLAYER_PLAYBACK_SPEED,
78   RYGEL_PLAYBIN_PLAYER_URI,
79   RYGEL_PLAYBIN_PLAYER_MIME_TYPE,
80   RYGEL_PLAYBIN_PLAYER_METADATA,
81   RYGEL_PLAYBIN_PLAYER_CAN_SEEK,
82   RYGEL_PLAYBIN_PLAYER_CONTENT_FEATURES,
83   RYGEL_PLAYBIN_PLAYER_VOLUME,
84   RYGEL_PLAYBIN_PLAYER_DURATION,
85   RYGEL_PLAYBIN_PLAYER_POSITION
86 };
87
88 #define RYGEL_PLAYBIN_PLAYER_TRANSFER_MODE_STREAMING "Streaming"
89 #define RYGEL_PLAYBIN_PLAYER_TRANSFER_MODE_INTERACTIVE "Interactive"
90 #define RYGEL_PLAYBIN_PLAYER_PROTOCOL_INFO_TEMPLATE "http-get:%s:*:%s"
91
92 static void rygel_playbin_player_set_playbin (RygelPlaybinPlayer *self, GstElement *value);
93 static void rygel_playbin_player_setup_playbin (RygelPlaybinPlayer *self);
94 static gboolean rygel_playbin_player_real_seek (RygelMediaPlayer *base, gint64 time);
95 static gchar **rygel_playbin_player_real_get_protocols (RygelMediaPlayer *base, int *result_length1);
96 static gchar **rygel_playbin_player_real_get_mime_types (RygelMediaPlayer *base, int *result_length1);
97 static gboolean rygel_playbin_player_is_rendering_image (RygelPlaybinPlayer *self);
98 static void rygel_playbin_player_bus_handler (GstBus *bus, GstMessage *message, gpointer user_data);
99 static gchar *rygel_playbin_player_generate_basic_didl (RygelPlaybinPlayer *self);
100 static void rygel_playbin_player_on_source_setup (GstElement *sender, GstElement *source, gpointer user_data);
101 static void rygel_playbin_player_on_uri_notify (GObject *sender, GParamSpec *pspec, gpointer user_data);
102 static void rygel_playbin_player_finalize (GObject *obj);
103 static void _vala_rygel_playbin_player_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
104 static void _vala_rygel_playbin_player_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
105
106 static const gchar *RYGEL_PLAYBIN_PLAYER_PROTOCOLS[2] = {"http-get", "rtsp"};
107 static const gchar *RYGEL_PLAYBIN_PLAYER_MIME_TYPES[40] = {"audio/mpeg", "application/ogg", "audio/x-vorbis", "audio/x-vorbis+ogg", "audio/ogg", "audio/x-ms-wma", "audio/x-ms-asf", "audio/x-flac", "audio/x-flac+ogg", "audio/flac", "audio/mp4", "audio/vnd.dlna.adts", "audio/x-mod", "audio/x-wav", "audio/x-ac3", "audio/x-m4a", "audio/L16;rate=44100;channels=2", "audio/L16;rate=44100;channels=1", "audio/L16;channels=2;rate=44100", "audio/L16;channels=1;rate=44100", "audio/L16;rate=44100", "image/jpeg", "image/png", "video/x-theora", "video/x-theora+ogg", "video/x-oggm", "video/ogg", "video/x-dirac", "video/x-wmv", "video/x-wma", "video/x-msvideo", "video/x-3ivx", "video/x-3ivx", "video/x-matroska", "video/x-mkv", "video/mpeg", "video/mp4", "video/x-ms-asf", "video/x-xvid", "video/x-ms-wmv"};
108
109
110 static RygelPlaybinPlayer*
111 rygel_playbin_player_new (void) {
112   RygelPlaybinPlayer *self;
113
114   self = RYGEL_PLAYBIN_PLAYER (g_object_new (RYGEL_TYPE_PLAYBIN_PLAYER, NULL));
115
116   /* TODO: This should really be done via a construct property. */
117   GstElement *playbin = gst_element_factory_make ("playbin2", NULL);
118   if (playbin) {
119     gst_object_ref_sink (playbin);
120   }
121
122   rygel_playbin_player_set_playbin (self, playbin);
123   gst_object_unref (playbin);
124
125   self->priv->foreign = FALSE;
126   rygel_playbin_player_setup_playbin (self);
127
128   return self;
129 }
130
131 static RygelPlaybinPlayer* rygel_playbin_player_player = NULL;
132
133 RygelPlaybinPlayer*
134 rygel_playbin_player_get_default (void) {
135   if (!rygel_playbin_player_player) {
136     rygel_playbin_player_player = rygel_playbin_player_new ();
137   }
138
139   g_object_ref (rygel_playbin_player_player);
140   return rygel_playbin_player_player;
141 }
142
143
144 static gboolean
145 rygel_playbin_player_real_seek (RygelMediaPlayer *base, gint64 time) {
146   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
147   g_return_val_if_fail (self, FALSE);
148   g_return_val_if_fail (self->priv->_playbin, FALSE);
149
150   return gst_element_seek (self->priv->_playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, time * GST_USECOND, GST_SEEK_TYPE_NONE, (gint64) (-1));
151 }
152
153
154 static gchar**
155 rygel_playbin_player_real_get_protocols (RygelMediaPlayer *base, int *result_length) {
156   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
157   int length = 0;
158   gchar **result = NULL;
159   int i = 0;
160
161   g_return_val_if_fail (self, NULL);
162
163   length =  G_N_ELEMENTS (RYGEL_PLAYBIN_PLAYER_PROTOCOLS);
164
165   if (result_length) {
166     *result_length = length;
167   }
168
169   result = g_new0 (gchar*, length + 1);
170   for (i = 0; i < length; i++) {
171     result[i] = g_strdup (RYGEL_PLAYBIN_PLAYER_PROTOCOLS[i]);
172   }
173
174   return result;
175 }
176
177 static gchar**
178 rygel_playbin_player_real_get_mime_types (RygelMediaPlayer *base, int *result_length) {
179   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
180   int length = 0;
181   gchar **result = NULL;
182   int i = 0;
183
184   g_return_val_if_fail (self, NULL);
185
186   length =  G_N_ELEMENTS (RYGEL_PLAYBIN_PLAYER_MIME_TYPES);
187
188   if (result_length) {
189     *result_length = length;
190   }
191
192   result = g_new0 (gchar*, length + 1);
193   for (i = 0; i < length; i++) {
194     result[i] = g_strdup (RYGEL_PLAYBIN_PLAYER_MIME_TYPES[i]);
195   }
196
197   return result;
198 }
199
200
201 static gboolean
202 rygel_playbin_player_is_rendering_image (RygelPlaybinPlayer *self) {
203   GstElement* typefind = NULL;
204   GstCaps *caps = NULL;
205   GstStructure *structure = NULL;
206   const gchar *name = NULL;
207   gboolean result;
208
209   g_return_val_if_fail (self, FALSE);
210   g_return_val_if_fail (self->priv->_playbin, FALSE);
211
212   typefind = gst_bin_get_by_name (GST_BIN (self->priv->_playbin), "typefind");
213   g_return_val_if_fail (typefind, FALSE);
214
215   g_object_get (typefind, "caps", &caps, NULL);
216   g_return_val_if_fail (caps, FALSE);
217
218   structure = gst_caps_get_structure (caps, 0);
219   g_return_val_if_fail (structure, FALSE);
220
221   name = gst_structure_get_name (structure);
222   result = (g_strcmp0 (name, "image/jpeg") == 0) ||
223     (g_strcmp0 (name, "image/png") == 0);
224
225   gst_caps_unref (caps);
226   gst_object_unref (typefind);
227
228   return result;
229 }
230
231 static void
232 rygel_playbin_player_bus_handler (GstBus *bus, GstMessage *message, gpointer user_data) {
233   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (user_data);
234   g_return_if_fail (self);
235
236   g_return_if_fail (bus);
237   g_return_if_fail (message);
238
239   switch (message->type) {
240     case GST_MESSAGE_DURATION:
241     {
242       GstFormat format = GST_FORMAT_TIME;
243       if (gst_element_query_duration (self->priv->_playbin, &format, NULL)) {
244         g_object_notify (G_OBJECT (self), "duration");
245       }
246
247       break;
248     }
249     case GST_MESSAGE_STATE_CHANGED:
250     {
251       if (message->src == GST_OBJECT (self->priv->_playbin)) {
252         GstState old_state = 0;
253         GstState new_state = 0;
254         GstState pending = 0;
255         gst_message_parse_state_changed (message, &old_state, &new_state, &pending);
256         if (old_state == GST_STATE_READY && new_state == GST_STATE_PAUSED) {
257           if (self->priv->uri_update_hint) {
258             self->priv->uri_update_hint = FALSE;
259
260             gchar *current_uri = NULL;
261             g_object_get (self->priv->_playbin, "uri", &current_uri, NULL);
262
263             if (g_strcmp0 (self->priv->_uri, current_uri) != 0
264               && g_strcmp0 (current_uri, "") != 0) {
265
266               // uri changed externally
267               if (self->priv->_uri)
268                 g_free (self->priv->_uri);
269
270               gchar *uri = NULL;
271               g_object_get (self->priv->_playbin, "uri", &uri, NULL);
272               self->priv->_uri = uri;
273               g_object_notify (G_OBJECT (self), "uri");
274
275               gchar *metadata = rygel_playbin_player_generate_basic_didl (self);
276               rygel_media_player_set_metadata (RYGEL_MEDIA_PLAYER (self), metadata);
277               g_free (metadata);
278             }
279
280             g_free (current_uri);
281           }
282         }
283
284         if (pending == GST_STATE_VOID_PENDING
285           && !self->priv->buffering) {
286           switch (new_state) {
287             case GST_STATE_PAUSED:
288             {
289               rygel_media_player_set_playback_state (RYGEL_MEDIA_PLAYER (self), "PAUSED_PLAYBACK");
290               break;
291             }
292             case GST_STATE_NULL:
293             {
294               rygel_media_player_set_playback_state (RYGEL_MEDIA_PLAYER (self), "STOPPED");
295               break;
296             }
297             case GST_STATE_PLAYING:
298             {
299               rygel_media_player_set_playback_state (RYGEL_MEDIA_PLAYER (self), "PLAYING");
300               break;
301             }
302             default:
303             {
304               break;
305             }
306           }
307         }
308
309         if (old_state == GST_STATE_PAUSED
310           && new_state == GST_STATE_PLAYING) {
311           self->priv->buffering = FALSE;
312           rygel_media_player_set_playback_state (RYGEL_MEDIA_PLAYER (self), "PLAYING");
313         }
314       }
315
316       break;
317     }
318     case GST_MESSAGE_BUFFERING:
319     {
320       // Assume the original application takes care of this.
321       if (!self->priv->is_live || self->priv->foreign) {
322         gint percent = 0;
323         gst_message_parse_buffering (message, &percent);
324  
325         if (percent < 100) {
326           self->priv->buffering = TRUE;
327           gst_element_set_state (self->priv->_playbin, GST_STATE_PAUSED);
328         } else {
329           gst_element_set_state (self->priv->_playbin, GST_STATE_PLAYING);
330         }
331       }
332
333       break;
334     }
335     case GST_MESSAGE_CLOCK_LOST:
336     {
337       // Assume the original application takes care of this.
338       if (!self->priv->foreign) {
339         gst_element_set_state (self->priv->_playbin, GST_STATE_PAUSED);
340         gst_element_set_state (self->priv->_playbin, GST_STATE_PLAYING);
341       }
342
343       break;
344     }
345     case GST_MESSAGE_EOS:
346     {
347       if(!rygel_playbin_player_is_rendering_image (self)) {
348         g_debug ("rygel-playbin-player.c: EOS");
349         rygel_media_player_set_playback_state (RYGEL_MEDIA_PLAYER (self), "STOPPED");
350       } else {
351         g_debug ("rygel-playbin-player.c: Content is image. Ignoring EOS");
352       }
353
354       break;
355     }
356     case GST_MESSAGE_ERROR:
357     {
358       GError *error = NULL;
359       gchar *error_message = NULL;
360       gchar *name = gst_object_get_name (GST_OBJECT (self->priv->_playbin));
361
362       gst_message_parse_error (message, &error, &error_message);
363       g_warning ("Error from GStreamer element %s: %s (%s)",
364                  name,
365                  error->message,
366                  error_message);
367       g_free (name);
368       g_error_free (error);
369       g_free (error_message);
370       g_warning ("Going to STOPPED state");
371
372       rygel_media_player_set_playback_state (RYGEL_MEDIA_PLAYER (self), "STOPPED");
373
374       break;
375     }
376     default:
377     break;
378   }
379 }
380
381
382 /**
383  * Generate basic DIDLLite information.
384  *
385  * This is used when the URI gets changed externally. DLNA requires that a
386  * minimum DIDLLite is always present if the URI is not empty.
387  */
388 static gchar*
389 rygel_playbin_player_generate_basic_didl (RygelPlaybinPlayer *self) {
390   GUPnPDIDLLiteWriter *writer = NULL;
391   GUPnPDIDLLiteItem *item = NULL;
392   GUPnPDIDLLiteResource *resource = NULL;
393   GFile *file = NULL;
394   gchar *basename = NULL;
395   gchar *result = NULL;
396
397   g_return_val_if_fail (self, NULL);
398
399   writer = gupnp_didl_lite_writer_new (NULL);
400
401   item = gupnp_didl_lite_writer_add_item (writer);
402   gupnp_didl_lite_object_set_id ((GUPnPDIDLLiteObject*) item, "1");
403   gupnp_didl_lite_object_set_parent_id ((GUPnPDIDLLiteObject*) item, "-1");
404   gupnp_didl_lite_object_set_upnp_class ((GUPnPDIDLLiteObject*) item, "object.item");
405
406   resource = gupnp_didl_lite_object_add_resource ((GUPnPDIDLLiteObject*) item);
407   gupnp_didl_lite_resource_set_uri (resource, self->priv->_uri);
408
409   file = g_file_new_for_uri (self->priv->_uri);
410   basename = g_file_get_basename (file);
411   gupnp_didl_lite_object_set_title ((GUPnPDIDLLiteObject*) item, basename);
412   g_free (basename);
413
414   result = gupnp_didl_lite_writer_get_string (writer);
415
416   g_object_unref (file);
417   g_object_unref (resource);
418   g_object_unref (item);
419   g_object_unref (writer);
420
421   return result;
422 }
423
424
425 static void
426 rygel_playbin_player_on_source_setup (GstElement *sender G_GNUC_UNUSED, GstElement *source, gpointer user_data) {
427   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (user_data);
428
429   GstStructure *structure = NULL;
430
431   g_return_if_fail (self);
432   g_return_if_fail (source);
433
434   //We do not use GST_IS_SOUP_HTTP_SRC(), to avoid a build-time dependency on gst-plugins-good,
435   //though it will be needed at runtime.
436   if ((g_strcmp0 (G_OBJECT_TYPE_NAME (source), "GstSoupHTTPSrc") == 0) &&
437     self->priv->transfer_mode) {
438     g_debug ("rygel-playbin-player.c: Setting transfer mode to %s", self->priv->transfer_mode);
439     
440     structure = gst_structure_empty_new ("Extra Headers");
441     gst_structure_set (structure, "transferMode.dlna.org", G_TYPE_STRING, self->priv->transfer_mode, NULL);
442
443     g_object_set (source, "extra-headers", structure, NULL);
444
445     gst_structure_free (structure);
446   }
447 }
448
449 static void
450 rygel_playbin_player_on_uri_notify (GObject *sender G_GNUC_UNUSED, GParamSpec *pspec, gpointer user_data) {
451   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (user_data);
452
453   g_return_if_fail (self);
454   g_return_if_fail (pspec);
455
456   self->priv->uri_update_hint = TRUE;
457 }
458
459 static void
460 rygel_playbin_player_setup_playbin (RygelPlaybinPlayer *self) {
461   GstBus *bus = NULL;
462
463   g_return_if_fail (self);
464   g_return_if_fail (self->priv->_playbin);
465
466   self->priv->duration_hint = FALSE;
467
468   /* Needed to get "Stop" events from the playbin.
469    * We can do this because we have a bus watch.
470    */
471   self->priv->is_live = FALSE;
472
473   g_object_set (self->priv->_playbin, "auto-flush-bus", FALSE, NULL);
474   g_assert (self->priv->_playbin);
475
476   g_signal_connect_object (self->priv->_playbin, "source_setup", (GCallback) rygel_playbin_player_on_source_setup, self, 0);
477   g_signal_connect_object (self->priv->_playbin, "notify::uri", (GCallback) rygel_playbin_player_on_uri_notify, self, 0);
478
479   /* Bus handler */
480   bus = gst_element_get_bus (self->priv->_playbin);
481   g_return_if_fail (bus);
482
483   gst_bus_add_signal_watch (bus);
484   g_signal_connect_object (bus, "message", (GCallback) rygel_playbin_player_bus_handler, self, 0);
485
486   gst_object_unref (bus);
487 }
488
489
490 GstElement*
491 rygel_playbin_player_get_playbin (RygelPlaybinPlayer *self) {
492   g_return_val_if_fail (self, NULL);
493
494   /* TODO: Shouldn't we ref this, like other GStreamer getters? */
495   return self->priv->_playbin;
496 }
497
498 static void
499 rygel_playbin_player_set_playbin (RygelPlaybinPlayer *self, GstElement *value) {
500   g_return_if_fail (self);
501
502   if(self->priv->_playbin)
503     gst_object_unref (self->priv->_playbin);
504
505   gst_object_ref (value);
506   self->priv->_playbin = value;
507
508   g_object_notify (G_OBJECT (self), "playbin");
509 }
510
511
512 static gchar*
513 rygel_playbin_player_real_get_playback_state (RygelMediaPlayer *base) {
514   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
515
516   g_return_val_if_fail (self, NULL);
517
518   return g_strdup (self->priv->_playback_state);
519 }
520
521
522 static void
523 rygel_playbin_player_real_set_playback_state (RygelMediaPlayer *base, const gchar *value) {
524   GstElement *bin;
525   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
526
527   g_return_if_fail (self);
528
529   GstState state = 0;
530   GstState pending = 0;
531   gst_element_get_state (self->priv->_playbin, &state, &pending, (GstClockTime) GST_MSECOND);
532
533   g_debug ("rygel-playbin-player.c: Changing playback state to %s.", value);
534
535   if (g_strcmp0 (value, "STOPPED") == 0) {
536     if (self->priv->_playback_state)
537       g_free (self->priv->_playback_state);
538
539     if (state != GST_STATE_NULL ||
540       pending != GST_STATE_VOID_PENDING) {
541       self->priv->_playback_state = g_strdup ("TRANSITIONING");
542       gst_element_set_state (self->priv->_playbin, GST_STATE_NULL);
543     } else {
544       self->priv->_playback_state = g_strdup (value);
545     }
546   } else if (g_strcmp0 (value, "PAUSED_PLAYBACK") == 0) {
547     if (self->priv->_playback_state)
548       g_free (self->priv->_playback_state);
549
550     if (state != GST_STATE_PAUSED ||
551       pending != GST_STATE_VOID_PENDING) {
552       self->priv->_playback_state = g_strdup ("TRANSITIONING");
553       gst_element_set_state (self->priv->_playbin, GST_STATE_PAUSED);
554     } else {
555       self->priv->_playback_state = g_strdup (value);
556     }
557   } else if (g_strcmp0 (value, "PLAYING") == 0) {
558     if (self->priv->_playback_state)
559       g_free (self->priv->_playback_state);
560
561     if (state != GST_STATE_PLAYING ||
562       pending != GST_STATE_VOID_PENDING) {
563
564       bin = gst_element_factory_make ("pulsesink", NULL);
565       if (bin != NULL)
566         g_object_set (self->priv->_playbin, "audio-sink", bin, NULL);
567
568       self->priv->_playback_state = g_strdup ("TRANSITIONING");
569
570       /* This needs a check if GStreamer and DLNA agree on
571        * the "liveness" of the source (s0/sn increase in
572        * protocol info.
573        */
574       self->priv->is_live = 
575         (gst_element_set_state (self->priv->_playbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_NO_PREROLL);
576     } else {
577       self->priv->_playback_state = g_strdup (value);
578     }
579   } else if (g_strcmp0 (value, "EOS") == 0) {
580     if (self->priv->_playback_state)
581       g_free (self->priv->_playback_state);
582
583     self->priv->_playback_state = g_strdup (value);
584   }
585
586   g_object_notify (G_OBJECT (self), "playback-state");
587 }
588
589
590 static gchar**
591 rygel_playbin_player_real_get_allowed_playback_speeds (RygelMediaPlayer *base, int *result_length) {
592   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
593   gchar **result = NULL;
594   int i = 0;
595
596   g_return_val_if_fail (self, NULL);
597
598   if (result_length) {
599     *result_length = self->priv->_allowed_playback_speeds_length;
600   }
601
602   result = g_new0 (gchar*, self->priv->_allowed_playback_speeds_length + 1);
603   for (i = 0; i < self->priv->_allowed_playback_speeds_length; i++) {
604     result[i] = g_strdup (self->priv->_allowed_playback_speeds[i]);
605   }
606
607   return result;
608 }
609
610
611 static gchar*
612 rygel_playbin_player_real_get_playback_speed (RygelMediaPlayer *base) {
613   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
614
615   g_return_val_if_fail (self, NULL);
616
617   return g_strdup (self->priv->_playback_speed);
618 }
619
620
621 static void rygel_playbin_player_real_set_playback_speed (RygelMediaPlayer *base, const gchar *value) {
622   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
623
624   g_return_if_fail (self);
625
626   if (self->priv->_playback_speed)
627     g_free (self->priv->_playback_speed);
628
629   self->priv->_playback_speed = g_strdup (value);
630
631   g_object_notify (G_OBJECT (self), "playback-speed");
632 }
633
634
635 static gchar*
636 rygel_playbin_player_real_get_uri (RygelMediaPlayer *base) {
637   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
638
639   g_return_val_if_fail (self, NULL);
640
641   return g_strdup (self->priv->_uri);
642 }
643
644
645 static void
646 rygel_playbin_player_real_set_uri (RygelMediaPlayer *base, const gchar *value) {
647   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
648
649   g_return_if_fail (self);
650
651   if (self->priv->_uri)
652     g_free (self->priv->_uri);
653   self->priv->_uri = g_strdup (value);
654
655   gst_element_set_state (self->priv->_playbin, GST_STATE_READY);
656   g_object_set (self->priv->_playbin, "uri", value, NULL);
657
658   if (g_strcmp0 (value, "") != 0) {
659     if (g_strcmp0 (self->priv->_playback_state, "NO_MEDIA_PRESENT") != 0) {
660       if (self->priv->_playback_state)
661         g_free (self->priv->_playback_state);
662
663       self->priv->_playback_state = g_strdup ("STOPPED");
664       g_object_notify (G_OBJECT (self), "playback-state");
665     } else if (g_strcmp0 (self->priv->_playback_state, "STOPPED") != 0) {
666     } else if (g_strcmp0 (self->priv->_playback_state, "PAUSED_PLAYBACK") != 0) {
667       self->priv->is_live = 
668         (gst_element_set_state (self->priv->_playbin, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL);
669     } else if (g_strcmp0 (self->priv->_playback_state, "EOS") != 0 ||
670       g_strcmp0 (self->priv->_playback_state, "PLAYING") != 0) {
671       /* This needs a check if GStreamer and DLNA agree on
672        * the "liveness" of the source (s0/sn increase in
673        * protocol info.
674        */
675       self->priv->is_live = 
676         (gst_element_set_state (self->priv->_playbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_NO_PREROLL);
677     }
678   } else {
679    if (self->priv->_playback_state)
680      g_free (self->priv->_playback_state);
681
682     self->priv->_playback_state = g_strdup ("NO_MEDIA_PRESENT");
683     g_object_notify (G_OBJECT (self), "playback-state");
684   }
685
686   g_debug ("rygel-playbin-player.c: URI set to %s.", value);
687 }
688
689
690 static gchar*
691 rygel_playbin_player_real_get_mime_type (RygelMediaPlayer *base) {
692   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
693
694   g_return_val_if_fail (self, NULL);
695
696   return g_strdup (self->priv->_mime_type);
697 }
698
699
700 static void
701 rygel_playbin_player_real_set_mime_type (RygelMediaPlayer *base, const gchar *value) {
702   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
703
704   g_return_if_fail (self);
705
706   if (self->priv->_mime_type)
707     g_free (self->priv->_mime_type);
708
709   self->priv->_mime_type = g_strdup (value);
710
711   g_object_notify (G_OBJECT (self), "mime-type");
712 }
713
714
715 static gchar*
716 rygel_playbin_player_real_get_metadata (RygelMediaPlayer *base) {
717   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
718
719   g_return_val_if_fail (self, NULL);
720
721   return g_strdup (self->priv->_metadata);
722 }
723
724
725 static void
726 rygel_playbin_player_real_set_metadata (RygelMediaPlayer *base, const gchar *value) {
727   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
728
729   g_return_if_fail (self);
730
731   if (self->priv->_metadata)
732     g_free (self->priv->_metadata);
733
734   self->priv->_metadata = g_strdup (value);
735
736   g_object_notify (G_OBJECT (self), "metadata");
737 }
738
739
740 static gboolean
741 rygel_playbin_player_real_get_can_seek (RygelMediaPlayer *base) {
742   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
743
744   g_return_val_if_fail (self, FALSE);
745
746   return (g_strcmp0 (self->priv->transfer_mode, RYGEL_PLAYBIN_PLAYER_TRANSFER_MODE_INTERACTIVE) != 0) &&
747     g_str_has_prefix (self->priv->_mime_type, "image/");
748 }
749
750
751 static gchar*
752 rygel_playbin_player_real_get_content_features (RygelMediaPlayer *base) {
753   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
754
755   g_return_val_if_fail (self, NULL);
756
757   return g_strdup (self->priv->_content_features);
758 }
759
760
761 static void
762 rygel_playbin_player_real_set_content_features (RygelMediaPlayer *base, const gchar *value) {
763   GError *inner_error = NULL;
764   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
765
766   g_return_if_fail (self);
767
768   gchar *mime_type = rygel_media_player_get_mime_type (RYGEL_MEDIA_PLAYER (self));
769   gchar *pi_string = g_strdup_printf (RYGEL_PLAYBIN_PLAYER_PROTOCOL_INFO_TEMPLATE,
770     mime_type, value);
771   g_free (mime_type);
772
773   if (self->priv->protocol_info)
774     g_object_unref (self->priv->protocol_info);
775
776   self->priv->protocol_info = gupnp_protocol_info_new_from_string (pi_string, &inner_error);
777   if (inner_error) {
778     if (self->priv->protocol_info)
779      g_object_unref (self->priv->protocol_info);
780     self->priv->protocol_info = NULL;
781
782     if (self->priv->transfer_mode)
783       g_free (self->priv->transfer_mode);
784     self->priv->transfer_mode = NULL;
785
786     g_error_free (inner_error);
787   }
788
789   if (self->priv->transfer_mode)
790     g_free (self->priv->transfer_mode);
791
792   GUPnPDLNAFlags flags = gupnp_protocol_info_get_dlna_flags (self->priv->protocol_info);
793   if ((flags & GUPNP_DLNA_FLAGS_INTERACTIVE_TRANSFER_MODE) == GUPNP_DLNA_FLAGS_INTERACTIVE_TRANSFER_MODE) {
794     self->priv->transfer_mode = g_strdup (RYGEL_PLAYBIN_PLAYER_TRANSFER_MODE_INTERACTIVE);
795   } else if ((flags & GUPNP_DLNA_FLAGS_STREAMING_TRANSFER_MODE) == GUPNP_DLNA_FLAGS_STREAMING_TRANSFER_MODE) {
796     self->priv->transfer_mode = g_strdup (RYGEL_PLAYBIN_PLAYER_TRANSFER_MODE_STREAMING);
797   } else {
798      self->priv->transfer_mode = NULL;
799   }
800
801   if (self->priv->_content_features)
802     g_free (self->priv->_content_features);
803   self->priv->_content_features = g_strdup (value);
804
805   g_free (pi_string);
806   g_object_notify (G_OBJECT (self), "content-features");
807 }
808
809 static gdouble
810 rygel_playbin_player_real_get_volume (RygelMediaPlayer *base) {
811   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
812
813   g_return_val_if_fail (self, 0);
814   g_return_val_if_fail (self->priv->_playbin, 0);
815
816   gdouble result = 0;
817   g_object_get (self->priv->_playbin, "volume", &result, NULL);
818   return result;
819 }
820
821
822 static void
823 rygel_playbin_player_real_set_volume (RygelMediaPlayer *base, gdouble value) {
824   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
825
826   g_return_if_fail (self);
827
828   g_object_set (self->priv->_playbin, "volume", value, NULL);
829
830   g_debug ("rygel-playbin-player.c: volume set to %f.", value);
831   g_object_notify (G_OBJECT (self), "volume");
832 }
833
834
835 static gint64
836 rygel_playbin_player_real_get_duration (RygelMediaPlayer *base) {
837   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
838   GstFormat format = GST_FORMAT_TIME;
839   gint64 pos = 0LL;
840
841   g_return_val_if_fail (self, 0LL);
842   g_return_val_if_fail (self->priv->_playbin, 0LL);
843
844   if (gst_element_query_duration (self->priv->_playbin, &format, &pos)) {
845     return pos / GST_USECOND;
846   } else {
847     return 0LL;
848   }
849 }
850
851
852 static gint64
853 rygel_playbin_player_real_get_position (RygelMediaPlayer *base) {
854   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (base);
855   GstFormat format = GST_FORMAT_TIME;
856   gint64 pos = 0LL;
857
858   g_return_val_if_fail (self, 0LL);
859   g_return_val_if_fail (self->priv->_playbin, 0LL);
860
861   if (gst_element_query_position (self->priv->_playbin, &format, &pos)) {
862     return pos / GST_USECOND;
863   } else {
864     return 0LL;
865   }
866 }
867
868
869 static void rygel_playbin_player_class_init (RygelPlaybinPlayerClass *klass) {
870   rygel_playbin_player_parent_class = g_type_class_peek_parent (klass);
871   g_type_class_add_private (klass, sizeof (RygelPlaybinPlayerPrivate));
872
873   G_OBJECT_CLASS (klass)->get_property = _vala_rygel_playbin_player_get_property;
874   G_OBJECT_CLASS (klass)->set_property = _vala_rygel_playbin_player_set_property;
875   G_OBJECT_CLASS (klass)->finalize = rygel_playbin_player_finalize;
876
877   g_object_class_install_property (G_OBJECT_CLASS (klass),
878     RYGEL_PLAYBIN_PLAYER_PLAYBIN,
879     g_param_spec_object ("playbin", "playbin", "playbin", GST_TYPE_ELEMENT,
880       G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
881
882   g_object_class_install_property (G_OBJECT_CLASS (klass),
883     RYGEL_PLAYBIN_PLAYER_PLAYBACK_STATE,
884     g_param_spec_string ("playback-state", "playback-state", "playback-state", NULL,
885       G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
886
887   g_object_class_install_property (G_OBJECT_CLASS (klass),
888     RYGEL_PLAYBIN_PLAYER_ALLOWED_PLAYBACK_SPEEDS,
889     g_param_spec_boxed ("allowed-playback-speeds", "allowed-playback-speeds", "allowed-playback-speeds",
890       G_TYPE_STRV, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
891
892   g_object_class_install_property (G_OBJECT_CLASS (klass),
893     RYGEL_PLAYBIN_PLAYER_PLAYBACK_SPEED,
894     g_param_spec_string ("playback-speed", "playback-speed", "playback-speed", NULL,
895       G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
896
897   g_object_class_install_property (G_OBJECT_CLASS (klass),
898      RYGEL_PLAYBIN_PLAYER_URI,
899      g_param_spec_string ("uri", "uri", "uri", NULL,
900       G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
901
902   g_object_class_install_property (G_OBJECT_CLASS (klass),
903     RYGEL_PLAYBIN_PLAYER_MIME_TYPE,
904      g_param_spec_string ("mime-type", "mime-type", "mime-type", NULL,
905       G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
906
907   g_object_class_install_property (G_OBJECT_CLASS (klass),
908     RYGEL_PLAYBIN_PLAYER_METADATA,
909     g_param_spec_string ("metadata", "metadata", "metadata", NULL,
910       G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
911
912   g_object_class_install_property (G_OBJECT_CLASS (klass),
913     RYGEL_PLAYBIN_PLAYER_CAN_SEEK,
914     g_param_spec_boolean ("can-seek", "can-seek", "can-seek", FALSE,
915       G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
916
917   g_object_class_install_property (G_OBJECT_CLASS (klass),
918     RYGEL_PLAYBIN_PLAYER_CONTENT_FEATURES,
919     g_param_spec_string ("content-features", "content-features", "content-features", NULL,
920       G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
921
922   g_object_class_install_property (G_OBJECT_CLASS (klass),
923     RYGEL_PLAYBIN_PLAYER_VOLUME,
924     g_param_spec_double ("volume", "volume", "volume", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
925       G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
926
927   g_object_class_install_property (G_OBJECT_CLASS (klass),
928     RYGEL_PLAYBIN_PLAYER_DURATION,
929     g_param_spec_int64 ("duration", "duration", "duration", G_MININT64, G_MAXINT64, 0,
930       G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
931
932   g_object_class_install_property (G_OBJECT_CLASS (klass),
933     RYGEL_PLAYBIN_PLAYER_POSITION,
934     g_param_spec_int64 ("position", "position", "position", G_MININT64, G_MAXINT64, 0,
935       G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
936 }
937
938
939 static void rygel_playbin_player_rygel_media_player_interface_init (RygelMediaPlayerIface *iface) {
940   rygel_playbin_player_rygel_media_player_parent_iface = g_type_interface_peek_parent (iface);
941
942   iface->seek = (gboolean (*)(RygelMediaPlayer*, gint64)) rygel_playbin_player_real_seek;
943   iface->get_protocols = (gchar **(*)(RygelMediaPlayer*, int*)) rygel_playbin_player_real_get_protocols;
944   iface->get_mime_types = (gchar **(*)(RygelMediaPlayer*, int*)) rygel_playbin_player_real_get_mime_types;
945   iface->get_playback_state = rygel_playbin_player_real_get_playback_state;
946   iface->set_playback_state = rygel_playbin_player_real_set_playback_state;
947   iface->get_allowed_playback_speeds = rygel_playbin_player_real_get_allowed_playback_speeds;
948   iface->get_playback_speed = rygel_playbin_player_real_get_playback_speed;
949   iface->set_playback_speed = rygel_playbin_player_real_set_playback_speed;
950   iface->get_uri = rygel_playbin_player_real_get_uri;
951   iface->set_uri = rygel_playbin_player_real_set_uri;
952   iface->get_mime_type = rygel_playbin_player_real_get_mime_type;
953   iface->set_mime_type = rygel_playbin_player_real_set_mime_type;
954   iface->get_metadata = rygel_playbin_player_real_get_metadata;
955   iface->set_metadata = rygel_playbin_player_real_set_metadata;
956   iface->get_can_seek = rygel_playbin_player_real_get_can_seek;
957   iface->get_content_features = rygel_playbin_player_real_get_content_features;
958   iface->set_content_features = rygel_playbin_player_real_set_content_features;
959   iface->get_volume = rygel_playbin_player_real_get_volume;
960   iface->set_volume = rygel_playbin_player_real_set_volume;
961   iface->get_duration = rygel_playbin_player_real_get_duration;
962   iface->get_position = rygel_playbin_player_real_get_position;
963 }
964
965
966 static void rygel_playbin_player_init (RygelPlaybinPlayer *self) {
967   g_return_if_fail (self);
968
969   self->priv = RYGEL_PLAYBIN_PLAYER_GET_PRIVATE (self);
970
971   self->priv->_playback_state = g_strdup ("NO_MEDIA_PRESENT");
972   self->priv->transfer_mode = NULL;
973   self->priv->uri_update_hint = FALSE;
974   self->priv->_uri = NULL;
975   self->priv->_mime_type = NULL;
976   self->priv->_metadata = NULL;
977   self->priv->_content_features = NULL;
978   self->priv->_allowed_playback_speeds = g_strsplit ("1", ",", -1);
979   self->priv->_allowed_playback_speeds_length = 1;
980   self->priv->_playback_speed = g_strdup ("1");
981 }
982
983
984 static void rygel_playbin_player_finalize (GObject *obj) {
985   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (obj);
986  
987   g_return_if_fail (self);
988
989   gst_object_unref (self->priv->_playbin);
990
991   if (self->priv->_playback_state)    
992     g_free (self->priv->_playback_state);
993
994   if (self->priv->_allowed_playback_speeds) {
995     int i;
996     for (i = 0; i < self->priv->_allowed_playback_speeds_length; i = i + 1) {
997       g_free (self->priv->_allowed_playback_speeds[i]);
998     }
999     g_free (self->priv->_allowed_playback_speeds);
1000   }
1001
1002   if (self->priv->_playback_speed)
1003     g_free (self->priv->_playback_speed);
1004
1005   if (self->priv->transfer_mode)
1006     g_free (self->priv->transfer_mode);
1007
1008   if (self->priv->_uri)
1009     g_free (self->priv->_uri);
1010
1011   if (self->priv->_mime_type)
1012     g_free (self->priv->_mime_type);
1013   
1014   if (self->priv->_metadata)
1015     g_free (self->priv->_metadata);
1016   
1017   if (self->priv->_content_features)
1018     g_free (self->priv->_content_features);
1019   
1020   if (self->priv->protocol_info)
1021     g_object_unref (self->priv->protocol_info);
1022
1023   G_OBJECT_CLASS (rygel_playbin_player_parent_class)->finalize (obj);
1024 }
1025
1026
1027 static void _vala_rygel_playbin_player_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) {
1028   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (object);
1029
1030   g_return_if_fail (self);
1031
1032   switch (property_id) {
1033     case RYGEL_PLAYBIN_PLAYER_PLAYBIN:
1034       g_value_set_object (value, rygel_playbin_player_get_playbin (self));
1035       break;
1036     case RYGEL_PLAYBIN_PLAYER_PLAYBACK_STATE:
1037       g_value_take_string (value, rygel_media_player_get_playback_state (RYGEL_MEDIA_PLAYER (self)));
1038       break;
1039     case RYGEL_PLAYBIN_PLAYER_ALLOWED_PLAYBACK_SPEEDS:
1040     {
1041       int length = 0;
1042       g_value_take_boxed (value, rygel_media_player_get_allowed_playback_speeds (RYGEL_MEDIA_PLAYER (self), &length));
1043       break;
1044     }
1045     case RYGEL_PLAYBIN_PLAYER_PLAYBACK_SPEED:
1046       g_value_take_string (value, rygel_media_player_get_playback_speed (RYGEL_MEDIA_PLAYER (self)));
1047       break;
1048     case RYGEL_PLAYBIN_PLAYER_URI:
1049       g_value_take_string (value, rygel_media_player_get_uri (RYGEL_MEDIA_PLAYER (self)));
1050       break;
1051     case RYGEL_PLAYBIN_PLAYER_MIME_TYPE:
1052       g_value_take_string (value, rygel_media_player_get_mime_type (RYGEL_MEDIA_PLAYER (self)));
1053       break;
1054     case RYGEL_PLAYBIN_PLAYER_METADATA:
1055       g_value_take_string (value, rygel_media_player_get_metadata (RYGEL_MEDIA_PLAYER (self)));
1056       break;
1057     case RYGEL_PLAYBIN_PLAYER_CAN_SEEK:
1058       g_value_set_boolean (value, rygel_media_player_get_can_seek (RYGEL_MEDIA_PLAYER (self)));
1059       break;
1060     case RYGEL_PLAYBIN_PLAYER_CONTENT_FEATURES:
1061       g_value_take_string (value, rygel_media_player_get_content_features (RYGEL_MEDIA_PLAYER (self)));
1062       break;
1063     case RYGEL_PLAYBIN_PLAYER_VOLUME:
1064       g_value_set_double (value, rygel_media_player_get_volume (RYGEL_MEDIA_PLAYER (self)));
1065       break;
1066     case RYGEL_PLAYBIN_PLAYER_DURATION:
1067       g_value_set_int64 (value, rygel_media_player_get_duration (RYGEL_MEDIA_PLAYER (self)));
1068       break;
1069     case RYGEL_PLAYBIN_PLAYER_POSITION:
1070       g_value_set_int64 (value, rygel_media_player_get_position (RYGEL_MEDIA_PLAYER (self)));
1071       break;
1072     default:
1073       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1074     break;
1075   }
1076 }
1077
1078
1079 static void _vala_rygel_playbin_player_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) {
1080   RygelPlaybinPlayer *self = RYGEL_PLAYBIN_PLAYER (object);
1081
1082   g_return_if_fail (self);
1083
1084   switch (property_id) {
1085     case RYGEL_PLAYBIN_PLAYER_PLAYBIN:
1086       rygel_playbin_player_set_playbin (self, g_value_get_object (value));
1087       break;
1088     case RYGEL_PLAYBIN_PLAYER_PLAYBACK_STATE:
1089       rygel_media_player_set_playback_state (RYGEL_MEDIA_PLAYER (self), g_value_get_string (value));
1090       break;
1091     case RYGEL_PLAYBIN_PLAYER_PLAYBACK_SPEED:
1092       rygel_media_player_set_playback_speed (RYGEL_MEDIA_PLAYER (self), g_value_get_string (value));
1093       break;
1094     case RYGEL_PLAYBIN_PLAYER_URI:
1095       rygel_media_player_set_uri (RYGEL_MEDIA_PLAYER (self), g_value_get_string (value));
1096       break;
1097     case RYGEL_PLAYBIN_PLAYER_MIME_TYPE:
1098       rygel_media_player_set_mime_type (RYGEL_MEDIA_PLAYER (self), g_value_get_string (value));
1099       break;
1100     case RYGEL_PLAYBIN_PLAYER_METADATA:
1101       rygel_media_player_set_metadata (RYGEL_MEDIA_PLAYER (self), g_value_get_string (value));
1102       break;
1103     case RYGEL_PLAYBIN_PLAYER_CONTENT_FEATURES:
1104       rygel_media_player_set_content_features (RYGEL_MEDIA_PLAYER (self), g_value_get_string (value));
1105       break;
1106     case RYGEL_PLAYBIN_PLAYER_VOLUME:
1107       rygel_media_player_set_volume (RYGEL_MEDIA_PLAYER (self), g_value_get_double (value));
1108       break;
1109     default:
1110       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1111       break;
1112   }
1113 }
1114