[rygel] server: Refactor transferMode handling



commit 2970c0f22938167a4e6d516205edf19900474158
Author: Jens Georg <mail jensge org>
Date:   Mon Jan 19 08:45:41 2015 +0100

    server: Refactor transferMode handling
    
    Based on Cablelabs's CVP-2 implementation.

 src/librygel-server/rygel-audio-item.vala          |    1 +
 src/librygel-server/rygel-http-get-handler.vala    |   36 +++++++++++++---
 src/librygel-server/rygel-http-get.vala            |   44 +++++--------------
 .../rygel-http-identity-handler.vala               |    4 ++
 .../rygel-http-resource-handler.vala               |   10 ++++
 .../rygel-http-transcode-handler.vala              |    9 ++++
 src/librygel-server/rygel-video-item.vala          |   14 ------
 7 files changed, 65 insertions(+), 53 deletions(-)
---
diff --git a/src/librygel-server/rygel-audio-item.vala b/src/librygel-server/rygel-audio-item.vala
index ec9b4c7..0495ecc 100644
--- a/src/librygel-server/rygel-audio-item.vala
+++ b/src/librygel-server/rygel-audio-item.vala
@@ -120,6 +120,7 @@ public class Rygel.AudioItem : MediaFileItem {
         res.sample_freq = this.sample_freq;
         res.bits_per_sample = this.bits_per_sample;
         res.audio_channels = this.channels;
+        res.dlna_flags |= DLNAFlags.STREAMING_TRANSFER_MODE;
 
         return res;
     }
diff --git a/src/librygel-server/rygel-http-get-handler.vala b/src/librygel-server/rygel-http-get-handler.vala
index 2d88881..c61b346 100644
--- a/src/librygel-server/rygel-http-get-handler.vala
+++ b/src/librygel-server/rygel-http-get-handler.vala
@@ -28,20 +28,21 @@ using GUPnP;
  * HTTP GET request handler interface.
  */
 internal abstract class Rygel.HTTPGetHandler: GLib.Object {
-    private const string TRANSFER_MODE_HEADER = "transferMode.dlna.org";
+    protected const string TRANSFER_MODE_HEADER = "transferMode.dlna.org";
+
+    protected const string TRANSFER_MODE_STREAMING = "Streaming";
+    protected const string TRANSFER_MODE_INTERACTIVE = "Interactive";
+    protected const string TRANSFER_MODE_BACKGROUND = "Background";
 
     public Cancellable cancellable { get; set; }
 
     // Add response headers.
+    /**
+     * Invokes the handler to add response headers to/for the given HTTP request
+     */
     public virtual void add_response_headers (HTTPGet request)
                                               throws HTTPRequestError {
         var mode = request.msg.request_headers.get_one (TRANSFER_MODE_HEADER);
-        if (mode != null) {
-            // FIXME: Is it OK to just copy the value of this header from
-            // request to response? All we do to entertain this header is to
-            // set the priority of IO operations.
-            request.msg.response_headers.append (TRANSFER_MODE_HEADER, mode);
-        }
 
         // Yes, I know this is not the ideal code to just get a specific
         // string for an HTTP header but if you think you can come-up with
@@ -61,6 +62,14 @@ internal abstract class Rygel.HTTPGetHandler: GLib.Object {
             warning ("Received request for 'contentFeatures.dlna.org' but " +
                        "failed to provide the value in response headers");
         }
+        // Per DLNA 7.5.4.3.2.33.2, if the transferMode header is empty it
+        // must be treated as Streaming mode or Interactive, depending upon the content
+        if (mode == null) {
+            request.msg.response_headers.append (TRANSFER_MODE_HEADER,
+                                                 this.get_default_transfer_mode ());
+        } else {
+            request.msg.response_headers.append (TRANSFER_MODE_HEADER, mode);
+        }
 
         // Handle device-specific hacks that need to change the response
         // headers such as Samsung's subtitle stuff.
@@ -72,6 +81,19 @@ internal abstract class Rygel.HTTPGetHandler: GLib.Object {
     }
 
     /**
+     * Returns the default transfer mode for the handler.
+     * The default is "Interactive"
+     */
+    public virtual string get_default_transfer_mode () {
+        return TRANSFER_MODE_INTERACTIVE; // Considering this the default
+    }
+
+    /**
+     * Returns true if the handler supports the given transfer mode, false otherwise.
+     */
+    public abstract bool supports_transfer_mode (string mode);
+
+    /**
      * Returns the resource size or -1 if not known.
      */
     public abstract int64 get_resource_size ();
diff --git a/src/librygel-server/rygel-http-get.vala b/src/librygel-server/rygel-http-get.vala
index b3fd5b9..0e7f602 100644
--- a/src/librygel-server/rygel-http-get.vala
+++ b/src/librygel-server/rygel-http-get.vala
@@ -82,7 +82,18 @@ internal class Rygel.HTTPGet : HTTPRequest {
             this.handler = new HTTPIdentityHandler (this.cancellable);
         }
 
-        this.ensure_correct_mode ();
+        { // Check the transfer mode
+            var transfer_mode = this.msg.request_headers.get_one (TRANSFER_MODE_HEADER);
+
+            if (transfer_mode == null) {
+                transfer_mode = this.handler.get_default_transfer_mode ();
+            }
+
+            if (! this.handler.supports_transfer_mode (transfer_mode)) {
+                throw new HTTPRequestError.UNACCEPTABLE ("%s transfer mode not supported for '%s'",
+                                                        transfer_mode, uri.to_string ());
+            }
+        }
 
         yield this.handle_item_request ();
     }
@@ -234,35 +245,4 @@ internal class Rygel.HTTPGet : HTTPRequest {
 
         this.end (Soup.Status.NONE);
     }
-
-    private void ensure_correct_mode () throws HTTPRequestError {
-        var mode = this.msg.request_headers.get_one (TRANSFER_MODE_HEADER);
-        var correct = true;
-
-        switch (mode) {
-        case "Streaming":
-            correct = (
-                      (this.handler is HTTPTranscodeHandler ||
-                      ((this.object as MediaFileItem).streamable () &&
-                       this.subtitle == null &&
-                       this.thumbnail == null)));
-
-            break;
-        case "Interactive":
-            correct = (this.handler is HTTPIdentityHandler &&
-                      ((!(this.object as MediaFileItem).is_live_stream () &&
-                       !(this.object as MediaFileItem).streamable ()) ||
-                       (this.subtitle != null ||
-                        this.thumbnail != null)));
-
-            break;
-        }
-
-        if (!correct) {
-            throw new HTTPRequestError.UNACCEPTABLE
-                                        ("%s mode not supported for '%s'",
-                                         mode,
-                                         this.object.id);
-        }
-    }
 }
diff --git a/src/librygel-server/rygel-http-identity-handler.vala 
b/src/librygel-server/rygel-http-identity-handler.vala
index 6c8b126..383f057 100644
--- a/src/librygel-server/rygel-http-identity-handler.vala
+++ b/src/librygel-server/rygel-http-identity-handler.vala
@@ -65,6 +65,10 @@ internal class Rygel.HTTPIdentityHandler : Rygel.HTTPGetHandler {
         }
     }
 
+    public override bool supports_transfer_mode (string mode) {
+        return true;
+    }
+
     public override int64 get_resource_size () {
         return -1;
     }
diff --git a/src/librygel-server/rygel-http-resource-handler.vala 
b/src/librygel-server/rygel-http-resource-handler.vala
index b1ed7ab..eae7246 100644
--- a/src/librygel-server/rygel-http-resource-handler.vala
+++ b/src/librygel-server/rygel-http-resource-handler.vala
@@ -63,6 +63,16 @@ internal class Rygel.HTTPMediaResourceHandler : HTTPGetHandler {
         base.add_response_headers (request);
     }
 
+    public override string get_default_transfer_mode () {
+        // Per DLNA 7.5.4.3.2.33.2, the assumed transfer mode is based on the content type
+        // "Streaming" for AV content and "Interactive" for all others
+        return media_resource.get_default_transfer_mode ();
+    }
+
+    public override bool supports_transfer_mode (string mode) {
+        return media_resource.supports_transfer_mode (mode);
+    }
+
     public override HTTPResponse render_body (HTTPGet request)
                                               throws HTTPRequestError {
         try {
diff --git a/src/librygel-server/rygel-http-transcode-handler.vala 
b/src/librygel-server/rygel-http-transcode-handler.vala
index 94492da..bf318cd 100644
--- a/src/librygel-server/rygel-http-transcode-handler.vala
+++ b/src/librygel-server/rygel-http-transcode-handler.vala
@@ -71,6 +71,15 @@ internal class Rygel.HTTPTranscodeHandler : HTTPGetHandler {
         return -1;
     }
 
+    public override string get_default_transfer_mode () {
+        return TRANSFER_MODE_STREAMING;
+    }
+
+    public override bool supports_transfer_mode (string mode) {
+        return (mode == TRANSFER_MODE_STREAMING ||
+                mode == TRANSFER_MODE_BACKGROUND);
+    }
+
     protected override DIDLLiteResource add_resource
                                         (DIDLLiteObject didl_object,
                                          HTTPGet      request)
diff --git a/src/librygel-server/rygel-video-item.vala b/src/librygel-server/rygel-video-item.vala
index d0ca515..e59eb85 100644
--- a/src/librygel-server/rygel-video-item.vala
+++ b/src/librygel-server/rygel-video-item.vala
@@ -101,20 +101,6 @@ public class Rygel.VideoItem : AudioItem, VisualItem {
         }
     }
 
-    internal override void add_resources (DIDLLiteItem didl_item,
-                                          bool         allow_internal)
-                                          throws Error {
-        foreach (var subtitle in this.subtitles) {
-            var protocol = this.get_protocol_for_uri (subtitle.uri);
-
-            if (allow_internal || protocol != "internal") {
-                subtitle.add_didl_node (didl_item);
-            }
-        }
-
-        base.add_resources (didl_item, allow_internal);
-    }
-
     internal override MediaResource get_primary_resource () {
         var res = base.get_primary_resource ();
 


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