[rygel] renderer: Implement SetNextAVTransportURI



commit 8224488d9a5ea34e6c90f938f140f1af61824cb1
Author: Jussi Kukkonen <jussi kukkonen intel com>
Date:   Mon Dec 2 15:44:44 2013 +0200

    renderer: Implement SetNextAVTransportURI
    
    This is a simple implementation: It does not prefetch media.
    
    Things that will be tried on EOS or on "Next" action:
     * if there are songs to play on playlist, play next one
     * else if NEXTAVTransportURI is set, play that
     * else set state to "STOPPED" and track to 1.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=719721

 data/xml/AVTransport2.xml.in                       |   27 +++++-
 src/librygel-renderer/rygel-av-transport.vala      |  118 +++++++++++++++-----
 src/librygel-renderer/rygel-player-controller.vala |   52 +++++++++-
 3 files changed, 166 insertions(+), 31 deletions(-)
---
diff --git a/data/xml/AVTransport2.xml.in b/data/xml/AVTransport2.xml.in
index e9d929b..56f7b52 100644
--- a/data/xml/AVTransport2.xml.in
+++ b/data/xml/AVTransport2.xml.in
@@ -26,7 +26,32 @@
             </argument>
          </argumentList>
       </action>
-
+      <action>
+          <name>SetNextAVTransportURI</name>
+          <argumentList>
+              <argument>
+                  <name>InstanceID</name>
+                  <direction>in</direction>
+                  <relatedStateVariable>
+                      A_ARG_TYPE_InstanceID
+                  </relatedStateVariable>
+              </argument>
+              <argument>
+                  <name>NextURI</name>
+                  <direction>in</direction>
+                  <relatedStateVariable>
+                      NextAVTransportURI
+                  </relatedStateVariable>
+              </argument>
+              <argument>
+                  <name>NextURIMetaData</name>
+                  <direction>in</direction>
+                  <relatedStateVariable>
+                      NextAVTransportURIMetaData
+                  </relatedStateVariable>
+              </argument>
+          </argumentList>
+      </action>
       <action>
          <name>GetMediaInfo</name>
          <argumentList>
diff --git a/src/librygel-renderer/rygel-av-transport.vala b/src/librygel-renderer/rygel-av-transport.vala
index aef8d40..e9fed90 100644
--- a/src/librygel-renderer/rygel-av-transport.vala
+++ b/src/librygel-renderer/rygel-av-transport.vala
@@ -106,6 +106,8 @@ internal class Rygel.AVTransport : Service {
 
         action_invoked["SetAVTransportURI"].connect
                                         (this.set_av_transport_uri_cb);
+        action_invoked["SetNextAVTransportURI"].connect
+                                        (this.set_next_av_transport_uri_cb);
         action_invoked["GetMediaInfo"].connect (this.get_media_info_cb);
         action_invoked["GetMediaInfo_Ext"].connect (this.get_media_info_ex_cb);
         action_invoked["GetTransportInfo"].connect (this.get_transport_info_cb);
@@ -132,6 +134,8 @@ internal class Rygel.AVTransport : Service {
         this.controller.notify["metadata"].connect (this.notify_meta_data_cb);
         this.controller.notify["track-uri"].connect (this.notify_track_uri_cb);
         this.controller.notify["track-metadata"].connect (this.notify_track_meta_data_cb);
+        this.controller.notify["next-uri"].connect (this.notify_next_uri_cb);
+        this.controller.notify["next-metadata"].connect (this.notify_next_meta_data_cb);
 
         this.player.notify["duration"].connect (this.notify_duration_cb);
 
@@ -178,14 +182,15 @@ internal class Rygel.AVTransport : Service {
         log.log ("CurrentTrack",                 this.controller.track.to_string ());
         log.log ("CurrentTrackDuration",         this.player.duration_as_str);
         log.log ("CurrentMediaDuration",         this.player.duration_as_str);
-        log.log ("CurrentTrackMetaData",
-                 Markup.escape_text (this.controller.track_metadata));
+        log.log ("AVTransportURI",               this.controller.uri);
         log.log ("AVTransportURIMetaData",
                  Markup.escape_text (this.controller.metadata));
         log.log ("CurrentTrackURI",              this.controller.track_uri);
-        log.log ("AVTransportURI",               this.controller.uri);
-        log.log ("NextAVTransportURI",           "NOT_IMPLEMENTED");
-        log.log ("NextAVTransportURIMetaData",   "NOT_IMPLEMENTED");
+        log.log ("CurrentTrackMetaData",
+                 Markup.escape_text (this.controller.track_metadata));
+        log.log ("NextAVTransportURI",           this.controller.next_uri);
+        log.log ("NextAVTransportURIMetaData",
+                 Markup.escape_text (this.controller.next_metadata));
 
         value.init (typeof (string));
         value.set_string (log.finish ());
@@ -228,20 +233,25 @@ internal class Rygel.AVTransport : Service {
                         typeof (string),
                         out _metadata);
 
-        if (_uri.has_prefix ("http://";) || _uri.has_prefix ("https://";)) {
-            var message = new Message ("HEAD", _uri);
-            message.request_headers.append ("getContentFeatures.dlna.org",
-                                            "1");
-            message.finished.connect ((msg) => {
-                this.check_resource (msg, _uri, _metadata, action);
-            });
-
-            this.session.queue_message (message, null);
-        } else {
-            this.controller.set_single_play_uri (_uri, _metadata, null, null);
+        this.handle_new_transport_uri (action, _uri, _metadata);
+    }
 
-            action.return ();
+    private void set_next_av_transport_uri_cb (Service       service,
+                                               ServiceAction action) {
+        if (!this.check_instance_id (action)) {
+            return;
         }
+
+        string _uri, _metadata;
+
+        action.get ("NextURI",
+                        typeof (string),
+                        out _uri,
+                    "NextURIMetaData",
+                        typeof (string),
+                        out _metadata);
+
+        this.handle_new_transport_uri (action, _uri, _metadata);
     }
 
     private bool is_valid_mime_type (string? mime) {
@@ -654,22 +664,31 @@ internal class Rygel.AVTransport : Service {
                             this.player.duration_as_str);
     }
 
-    private void notify_track_uri_cb (Object player, ParamSpec p) {
-        this.changelog.log ("CurrentTrackURI", this.controller.track_uri);
-    }
-
     private void notify_uri_cb (Object controller, ParamSpec p) {
         this.changelog.log ("AVTransportURI", this.controller.uri);
     }
 
+    private void notify_meta_data_cb (Object player, ParamSpec p) {
+        this.changelog.log ("AVTransportURIMetaData",
+                            Markup.escape_text (this.controller.metadata));
+    }
+
+    private void notify_track_uri_cb (Object player, ParamSpec p) {
+        this.changelog.log ("CurrentTrackURI", this.controller.track_uri);
+    }
+
     private void notify_track_meta_data_cb (Object player, ParamSpec p) {
         this.changelog.log ("CurrentTrackMetaData",
                             Markup.escape_text (this.controller.track_metadata));
     }
 
-    private void notify_meta_data_cb (Object player, ParamSpec p) {
-        this.changelog.log ("AVTransportURIMetaData",
-                            Markup.escape_text (this.controller.metadata));
+    private void notify_next_uri_cb (Object controller, ParamSpec p) {
+        this.changelog.log ("NextAVTransportURI", this.controller.next_uri);
+    }
+
+    private void notify_next_meta_data_cb (Object player, ParamSpec p) {
+        this.changelog.log ("NextAVTransportURIMetaData",
+                            Markup.escape_text (this.controller.next_metadata));
     }
 
     private async void handle_playlist (ServiceAction action,
@@ -699,7 +718,16 @@ internal class Rygel.AVTransport : Service {
             return;
         }
 
-        this.controller.set_playlist_uri (uri, metadata, collection);
+        switch (action.get_name ()) {
+        case "SetAVTransportURI":
+            this.controller.set_playlist_uri (uri, metadata, collection);
+            break;
+        case "SetNextAVTransportURI":
+            this.controller.set_next_playlist_uri (uri, metadata, collection);
+            break;
+        default:
+            assert_not_reached ();
+        }
 
         action.return ();
     }
@@ -765,12 +793,44 @@ internal class Rygel.AVTransport : Service {
                                         _metadata,
                                         mime,
                                         features);
-
-            return;
+        } else {
+            this.set_single_play_uri (action, _uri, _metadata, mime, features);
         }
+    }
 
-        this.controller.set_single_play_uri (_uri, _metadata, mime, features);
+    private void handle_new_transport_uri (ServiceAction action,
+                                           string        uri,
+                                           string        metadata) {
+        if (uri.has_prefix ("http://";) || uri.has_prefix ("https://";)) {
+            var message = new Message ("HEAD", uri);
+            message.request_headers.append ("getContentFeatures.dlna.org",
+                                            "1");
+            message.finished.connect ((msg) => {
+                this.check_resource (msg, uri, metadata, action);
+            });
 
-        action.return ();
+            this.session.queue_message (message, null);
+        } else {
+            this.set_single_play_uri (action, uri, metadata, null, null);
+        }
+    }
+
+    private void set_single_play_uri (ServiceAction    action,
+                                      string           uri,
+                                      string           metadata,
+                                      string?          mime,
+                                      string?          features) {
+            switch (action.get_name ()) {
+            case "SetAVTransportURI":
+                this.controller.set_single_play_uri (uri, metadata, mime, features);
+                break;
+            case "SetNextAVTransportURI":
+                this.controller.set_next_single_play_uri (uri, metadata, mime, features);
+                break;
+            default:
+                assert_not_reached ();
+            }
+
+            action.return ();
     }
 }
diff --git a/src/librygel-renderer/rygel-player-controller.vala 
b/src/librygel-renderer/rygel-player-controller.vala
index c11bd06..e6975f9 100644
--- a/src/librygel-renderer/rygel-player-controller.vala
+++ b/src/librygel-renderer/rygel-player-controller.vala
@@ -116,6 +116,9 @@ internal class Rygel.PlayerController : Object {
         }
     }
 
+    public string next_uri { get; private set; default = ""; }
+    public string next_metadata { get; private set; default = ""; }
+
     public string current_transport_actions {
         owned get {
             string actions = null;
@@ -177,6 +180,10 @@ internal class Rygel.PlayerController : Object {
     private uint default_image_timeout;
     private Configuration config;
 
+    private string next_features;
+    private string next_mime;
+    private MediaCollection next_collection;
+
     // Private property variables
     private uint _n_tracks;
     private uint _track;
@@ -207,6 +214,28 @@ internal class Rygel.PlayerController : Object {
             return true;
         }
 
+        // Try playing next_uri
+        if (this.next_uri != "") {
+            if (this.next_collection != null) {
+                this.set_playlist_uri (this.next_uri,
+                                       this.next_metadata,
+                                       this.next_collection);
+            } else {
+                this.set_single_play_uri (this.next_uri,
+                                          this.next_metadata,
+                                          this.next_mime,
+                                          this.next_features);
+            }
+
+            this.next_uri = "";
+            this.next_metadata = "";
+            this.next_mime = null;
+            this.next_features = null;
+            this.next_collection = null;
+
+            return true;
+        }
+
         return false;
     }
 
@@ -274,10 +303,31 @@ internal class Rygel.PlayerController : Object {
         }
     }
 
+    public void set_next_single_play_uri (string uri,
+                                          string metadata,
+                                          string? mime,
+                                          string? features) {
+        this.next_uri = uri;
+        this.next_metadata = metadata;
+        this.next_mime = mime;
+        this.next_features = features;
+        this.next_collection = null;
+    }
+
+    public void set_next_playlist_uri (string uri,
+                                       string metadata,
+                                       MediaCollection collection) {
+        this.next_uri = uri;
+        this.next_metadata = metadata;
+        this.next_mime = null;
+        this.next_features = null;
+        this.next_collection = collection;
+    }
+
     private void notify_state_cb (Object player, ParamSpec p) {
         var state = this.player.playback_state;
         if (state == "EOS") {
-            // Play next item in playlist or move to STOPPED
+            // Play next item in playlist, play next_uri, or move to STOPPED
             Idle.add (() => {
                 if (!this.next ()) {
                     this.reset ();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]