diff --git a/src/librygel-server/rygel-media-engine.vala b/src/librygel-server/rygel-media-engine.vala
index 28d61b1..fb9680a 100644
--- a/src/librygel-server/rygel-media-engine.vala
+++ b/src/librygel-server/rygel-media-engine.vala
@@ -1,7 +1,9 @@
 /*
  * Copyright (C) 2012 Intel Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Jens Georg <jensg@openismus.com>
+ *         Craig Pratt <craig@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -26,10 +28,13 @@ public errordomain Rygel.MediaEngineError {
 
 /**
  * This is the base class for media engines that contain knowledge about 
- * the streaming and (optionally) the transcoding and seeking capabilites
- * of the media library in use. Derived classes also instantiate any
- * transcoding objects supported by the media engine and specify the list
- * of media formats the engine is capable of playing.
+ * the streaming and transformational capabilites of the media library in use.
+ *
+ * Media engines express what representations of a MediaObject they can
+ * produce by returning MediaResource objects which will, in turn, be
+ * used to express to endpoints representations can be streamed from
+ * the MediaServer. These representations may include transformations,
+ * time-scaled representations, and/or encrypted representations. 
  *
  * See, for instance, Rygel's built-in "gstreamer" and "simple" media engines,
  * or the external rygel-gst-0-10-media-engine module.
@@ -42,18 +47,6 @@ public errordomain Rygel.MediaEngineError {
  * Media engines should also derive their own #RygelDataSource,
  * returning an instance of it from create_data_source().
  *
- * If this media engine supports transcoding then it will typically
- * implement a set of transcoding classes, typically with one 
- * base class and a number of sub-classes - one for each transcoding
- * format you want to support. These should be returned by the
- * get_transcoders() virtual function. The base transcoder class could
- * provide a generic way to create a #RygelDataSource capable of
- * providing Rygel with a transcoded version of a file using the
- * underlying media framework. The sub-classes could contain the
- * various media-framework-specific parameters required to 
- * transcode to a given format and implement a heuristic that
- * can be used to order an item's transcoded resources.
- *
  * See the
  * <link linkend="implementing-media-engines">Implementing Media Engines</link> section.
  */
@@ -84,32 +77,53 @@ public abstract class Rygel.MediaEngine : GLib.Object {
     }
 
     /**
-     * Get a list of the DLNA profiles that are supported by this media
-     * engine when calling rygel_media_engine_create_data_source().
-     *
-     * Other DLNA profiles may be supported as transcoding targets -
+     * Get a list of the DLNA profiles that the media engine can stream.
      *
      * This information is needed to implement DLNA's
      * ConnectionManager.GetProtocolInfo call and to determine whether Rygel
      * can accept an uploaded file.
      *
      * @return A list of #RygelDLNAProfile<!-- -->s
-     * @see rygel_media_engine_get_transcoders().
      */
     public abstract unowned List<DLNAProfile> get_dlna_profiles ();
 
     /**
-     * Get a list of the transcoders that are provided by this media engine.
+     * Retrieve engine-provided resources for the given MediaObject
+     *
+     * The MediaResources returned may include formats/profiles that do not match the
+     * source content byte-for-byte (e.g. transcodes, encrypted formats, etc). The
+     * MediaEngine must return a MediaResource for the raw MediaObject content if it
+     * can support streaming the content directly. 
+     *
+     * The order of MediaResources in the returned List should be from most-preferred to
+     * least-preferred and each must have a unique alphanumeric "name" field.
+     * 
+     * Note: The engine should set all delivery-related flags assuming all delivery forms are
+     * supported (e.g. the protocol fields and delivery flags of the ProtocolInfo). And the
+     * resource uri should be set to the empty string for http-delivered resources. The 
+     * effective delivery options and uri will be established by the HTTP server.
+     *
+     * @return A list of #MediaResources<!-- -->s or null if no representations 
+     *         are provided by the engine for the item.
+     */
+    public abstract async Gee.List<MediaResource> ? get_resources_for_item (MediaObject item);
+
+    /**
+     * Get a #DataSource for given #MediaResource representation of the #MediaObject.
+     *
+     * @param item The #MediaObject to create the #DataSource for
+     * @param resource The specific resource to create the #DataSource for
      *
-     * @return A list of #RygelTranscoder<!-- -->s or null if not supported.
+     * @return A #DataSource representing the given item resource
      */
-    public abstract unowned List<Transcoder>? get_transcoders ();
+    public abstract DataSource? create_data_source_for_resource (MediaObject item,
+                                                                 MediaResource resource);
 
     /**
-     * Get a data source for the URI.
+     * Get a #DataSource for the URI.
      *
-     * @param uri to create the data source for.
-     * @return A data source representing the uri
+     * @param uri to create the #DataSource for.
+     * @return A #DataSource representing the uri
      */
-    public abstract DataSource? create_data_source (string uri);
+    public abstract DataSource? create_data_source_for_uri (string uri);
 }
diff --git a/src/media-engines/gstreamer/rygel-aac-transcoder.vala b/src/media-engines/gstreamer/rygel-aac-transcoder.vala
index bf5a36f..7a859b9 100644
--- a/src/media-engines/gstreamer/rygel-aac-transcoder.vala
+++ b/src/media-engines/gstreamer/rygel-aac-transcoder.vala
@@ -1,7 +1,9 @@
 /*
  * Copyright (C) 2011 Nokia Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Luis de Bethencourt <luis.debethencourt@collabora.com>
+ *         Prasanna Modem <prasanna@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -31,8 +33,9 @@ internal class Rygel.AACTranscoder : Rygel.AudioTranscoder {
     private const string CODEC = "audio/mpeg,mpegversion=4," +
                                  "stream-format=adts,rate=44100,base-profile=lc";
 
+    private const string NAME = "AAC_ADTS_320";
     public AACTranscoder () {
-        base ("audio/vnd.dlna.adts", "AAC_ADTS_320", BITRATE, null, CODEC, "adts");
+        base (NAME, "audio/vnd.dlna.adts", NAME, BITRATE, null, CODEC, "adts");
         this.preset = "Rygel AAC_ADTS_320 preset";
     }
 }
diff --git a/src/media-engines/gstreamer/rygel-audio-transcoder.vala b/src/media-engines/gstreamer/rygel-audio-transcoder.vala
index bdddc04..6aca760 100644
--- a/src/media-engines/gstreamer/rygel-audio-transcoder.vala
+++ b/src/media-engines/gstreamer/rygel-audio-transcoder.vala
@@ -1,8 +1,10 @@
 /*
  * Copyright (C) 2011 Nokia Corporation.
  * Copyright (C) 2012 Intel Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Jens Georg <jensg@openismus.com>
+ *         Prasanna Modem <prasanna@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -20,6 +22,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
+
 using Gst;
 using Gst.PbUtils;
 using GUPnP;
@@ -27,20 +30,21 @@ using GUPnP;
 /**
  * Base class for all transcoders that handle audio.
  */
-internal class Rygel.AudioTranscoder : Rygel.GstTranscoder {
+internal abstract class Rygel.AudioTranscoder : Rygel.GstTranscoder {
     protected int audio_bitrate;
     protected Caps container_format = null;
     protected Caps audio_codec_format = null;
 
     public const string NO_CONTAINER = null;
 
-    public AudioTranscoder (string  content_type,
+    public AudioTranscoder (string  name,
+                            string  content_type,
                             string  dlna_profile,
                             int     audio_bitrate,
                             string? container_caps,
                             string  audio_codec_caps,
                             string  extension) {
-        base (content_type, dlna_profile, extension);
+        base (name, content_type, dlna_profile, extension);
 
         this.audio_bitrate = audio_bitrate;
         if (container_caps != null) {
@@ -50,13 +54,14 @@ internal class Rygel.AudioTranscoder : Rygel.GstTranscoder {
         this.audio_codec_format = Caps.from_string (audio_codec_caps);
     }
 
-    public AudioTranscoder.with_class (string  content_type,
+    public AudioTranscoder.with_class (string  name,
+                                       string  content_type,
                                        string  dlna_profile,
                                        int     audio_bitrate,
                                        string? container_caps,
                                        string  audio_codec_caps,
                                        string  extension) {
-        base (content_type, dlna_profile, extension);
+        base (name, content_type, dlna_profile, extension);
 
         this.audio_bitrate = audio_bitrate;
         if (container_caps != null) {
@@ -66,22 +71,7 @@ internal class Rygel.AudioTranscoder : Rygel.GstTranscoder {
         this.audio_codec_format = Caps.from_string (audio_codec_caps);
     }
 
-
-    public override DIDLLiteResource? add_resource (DIDLLiteItem     didl_item,
-                                                    MediaItem        item,
-                                                    TranscodeManager manager)
-                                                    throws Error {
-        var resource = base.add_resource (didl_item, item, manager);
-        if (resource == null) {
-            return null;
-        }
-
-        resource.bitrate = (this.audio_bitrate * 1000) / 8;
-
-        return resource;
-    }
-
-    public override uint get_distance (MediaItem item) {
+    public override uint get_distance (MediaFileItem item) {
         if (!(item is AudioItem) || item is VideoItem) {
             return uint.MAX;
         }
@@ -115,4 +105,15 @@ internal class Rygel.AudioTranscoder : Rygel.GstTranscoder {
 
         return enc_audio_profile;
     }
+
+    public override MediaResource? get_resource_for_item (MediaFileItem item) {
+        var resource = base.get_resource_for_item (item);
+        if (resource == null) {
+            return null;
+        }
+
+        resource.sample_freq = this.audio_bitrate;
+
+        return resource;
+    }
 }
diff --git a/src/media-engines/gstreamer/rygel-avc-transcoder.vala b/src/media-engines/gstreamer/rygel-avc-transcoder.vala
index b53764b..e47882e 100644
--- a/src/media-engines/gstreamer/rygel-avc-transcoder.vala
+++ b/src/media-engines/gstreamer/rygel-avc-transcoder.vala
@@ -1,7 +1,9 @@
 /*
  * Copyright (C) 2011 Nokia Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Luis de Bethencourt <luis.debethencourt@collabora.com>
+ *         Prasanna Modem <prasanna@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -19,6 +21,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
+
 using Gst;
 using GUPnP;
 
@@ -37,9 +40,11 @@ internal class Rygel.AVCTranscoder : Rygel.VideoTranscoder {
     private const string RESTRICTIONS =
         "video/x-raw,framerate=(fraction)15/1,width=352,height=288";
 
+    private const string NAME = "AVC_MP4_BL_CIF15_AAC_520";
     public AVCTranscoder () {
-        base ("video/mp4",
-              "AVC_MP4_BL_CIF15_AAC_520",
+        base (NAME,
+              "video/mp4",
+              NAME,
               AUDIO_BITRATE,
               VIDEO_BITRATE,
               CONTAINER,
@@ -49,19 +54,4 @@ internal class Rygel.AVCTranscoder : Rygel.VideoTranscoder {
               RESTRICTIONS);
         this.preset = "Rygel AVC_MP4_BL_CIF15_AAC_520 preset";
     }
-
-    public override DIDLLiteResource? add_resource (DIDLLiteItem     didl_item,
-                                                    MediaItem        item,
-                                                    TranscodeManager manager)
-                                                    throws Error {
-        var resource = base.add_resource (didl_item, item, manager);
-        if (resource == null) {
-            return null;
-        }
-
-        resource.width = 352;
-        resource.height = 288;
-
-        return resource;
-    }
 }
diff --git a/src/media-engines/gstreamer/rygel-gst-data-source.vala b/src/media-engines/gstreamer/rygel-gst-data-source.vala
index 1e536f6..61c8311 100644
--- a/src/media-engines/gstreamer/rygel-gst-data-source.vala
+++ b/src/media-engines/gstreamer/rygel-gst-data-source.vala
@@ -1,7 +1,10 @@
 /*
  * Copyright (C) 2012 Intel Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Jens Georg <jensg@openismus.com>
+ *         Prasanna Modem <prasanna@ecaspia.com>
+ *         Craig Pratt <craig@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -28,12 +31,14 @@ internal errordomain Rygel.GstDataSourceError {
 
 internal class Rygel.GstDataSource : Rygel.DataSource, GLib.Object {
     internal dynamic Element src;
+    internal MediaResource res;
     private Pipeline pipeline;
-    private HTTPSeek seek = null;
+    private HTTPSeekRequest seek = null;
     private GstSink sink;
     private uint bus_watch_id;
 
-    public GstDataSource (string uri) throws Error {
+    public GstDataSource (string uri, MediaResource ? resource) throws Error {
+        this.res = resource;
         this.src = GstUtils.create_source_for_uri (uri);
         if (this.src == null) {
             var msg = _("Could not create GstElement for URI %s");
@@ -56,8 +61,44 @@ internal class Rygel.GstDataSource : Rygel.DataSource, GLib.Object {
         this.src = element;
     }
 
-    public void start (HTTPSeek? offsets) throws Error {
-        this.seek = offsets;
+    public Gee.List<HTTPResponseElement> ? preroll ( HTTPSeekRequest? seek_request,
+                                                     PlaySpeedRequest? playspeed_request)
+       throws Error {
+        var response_list = new Gee.ArrayList<HTTPResponseElement>();
+
+        if (playspeed_request != null) {
+            throw new DataSourceError.PLAYSPEED_FAILED
+                                    (_("Playspeed not supported"));
+        }
+
+        if (seek_request == null) {
+            debug("No seek requested - sending entire binary");
+        } else if (seek_request is HTTPByteSeekRequest) {
+            var seek_response = new HTTPByteSeekResponse.from_request( seek_request
+                                                                       as HTTPByteSeekRequest );
+            debug("Processing byte seek request for bytes %lld-%lld",
+                    seek_response.start_byte, seek_response.end_byte);
+            response_list.add(seek_response);
+            // Supported - and no reponse values required...
+        } else if (seek is HTTPTimeSeekRequest) {
+            var time_seek = seek_request as HTTPTimeSeekRequest;
+            // Set the effective TimeSeekRange response range to the requested range
+            // TODO: Align this with actual time range being returned
+            var seek_response = new HTTPTimeSeekResponse.from_request(time_seek, res.duration);
+            debug("Processing time seek request for %lldns-%lldns",
+                    seek_response.start_time, seek_response.end_time);
+            response_list.add(seek_response);
+        } else {
+            // Unknown/unsupported seek type
+            throw new DataSourceError.SEEK_FAILED
+                                    (_("HTTPSeekRequest type unsupported"));
+        }
+
+        this.seek = seek_request;
+        return response_list;
+    }
+
+    public void start () throws Error {
         this.prepare_pipeline ("RygelGstDataSource", this.src);
         if (this.seek != null) {
             this.pipeline.set_state (State.PAUSED);
@@ -215,29 +256,35 @@ internal class Rygel.GstDataSource : Rygel.DataSource, GLib.Object {
     }
 
     private bool perform_seek () {
-        if (this.seek != null &&
-            this.seek.length >= this.seek.total_length) {
-            return true;
-        }
-
         var stop_type = Gst.SeekType.NONE;
         Format format;
         var flags = SeekFlags.FLUSH;
         int64 start, stop;
 
-        if (this.seek.seek_type == HTTPSeekType.TIME) {
+        if (this.seek is HTTPTimeSeekRequest) {
+            var time_seek = this.seek as HTTPTimeSeekRequest;
             format = Format.TIME;
             flags |= SeekFlags.KEY_UNIT;
-            start = (this.seek.start) * Gst.USECOND;
-            stop = (this.seek.stop) * Gst.USECOND;
-        } else {
+            start = time_seek.start_time * Gst.USECOND;
+            stop = time_seek.end_time * Gst.USECOND;
+            debug("Performing time-range seek: %lldns to %lldns", start, stop);
+        } else if (this.seek is HTTPByteSeekRequest) {
+            var byte_seek = this.seek as HTTPByteSeekRequest;
+            if (byte_seek.range_length >= byte_seek.total_size) {
+                // How/why would this happen? 
+                return true;
+            }
             format = Format.BYTES;
             flags |= SeekFlags.ACCURATE;
-            start = this.seek.start;
-            stop = this.seek.stop;
+            start = byte_seek.start_byte;
+            stop = byte_seek.end_byte;
+            debug("Performing byte-range seek: bytes %lld to %lld", start, stop);
+        } else {
+            this.error (new DataSourceError.SEEK_FAILED (_("Unsupported seek type")));
+            return false;
         }
 
-        if (this.seek.stop > 0) {
+        if (stop > 0) {
             stop_type = Gst.SeekType.SET;
         }
 
@@ -249,8 +296,7 @@ internal class Rygel.GstDataSource : Rygel.DataSource, GLib.Object {
                                  stop_type,
                                  stop + 1)) {
             warning (_("Failed to seek to offsets %lld:%lld"),
-                     this.seek.start,
-                     this.seek.stop);
+                     start, stop);
 
             this.error (new DataSourceError.SEEK_FAILED (_("Failed to seek")));
 
diff --git a/src/media-engines/gstreamer/rygel-gst-media-engine.vala b/src/media-engines/gstreamer/rygel-gst-media-engine.vala
index 1486737..83d9e8c 100644
--- a/src/media-engines/gstreamer/rygel-gst-media-engine.vala
+++ b/src/media-engines/gstreamer/rygel-gst-media-engine.vala
@@ -1,7 +1,10 @@
 /*
  * Copyright (C) 2012 Intel Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Jens Georg <jensg@openismus.com>
+ *         Prasanna Modem <prasanna@ecaspia.com>
+ *         Craig Pratt <craig@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -22,6 +25,7 @@
 
 using Gst;
 using Gee;
+using GUPnP;
 
 // Remove for GStreamer 1.0
 [CCode (cname = "PRESET_DIR")]
@@ -32,7 +36,7 @@ extern bool gst_preset_set_app_dir (string app_dir);
 
 public class Rygel.GstMediaEngine : Rygel.MediaEngine {
     private GLib.List<DLNAProfile> dlna_profiles = null;
-    private GLib.List<Transcoder> transcoders = null;
+    private GLib.List<GstTranscoder> transcoders = null;
 
     public GstMediaEngine () {
         unowned string[] args = null;
@@ -112,16 +116,105 @@ public class Rygel.GstMediaEngine : Rygel.MediaEngine {
         return this.dlna_profiles;
     }
 
-    public override unowned GLib.List<Transcoder>? get_transcoders () {
-        return this.transcoders;
+    public override async Gee.List<MediaResource> ? get_resources_for_item (MediaObject object) {
+        if (! (object is MediaFileItem)) {
+            warning ("Can only process file-based MediaObjects (MediaFileItems)");
+            return null;
+        }
+
+        var item = object as MediaFileItem; 
+
+        // For MediaFileItems, uri 0 is the file URI referring directly to the content
+        string source_uri = item.uris.get (0);
+
+        debug ("get_resources_for_item(%s)", source_uri);
+
+        if (!source_uri.has_prefix ("file://")) {
+            warning ("Can't process non-file uri " + source_uri);
+            return null;
+        }
+
+        Gee.List<MediaResource> resources = new Gee.ArrayList<MediaResource> ();
+
+        var primary_res = item.get_primary_resource ();
+
+        // The GstMediaEngine only supports byte-based seek on the primary resource currently
+        primary_res.dlna_operation = DLNAOperation.RANGE;
+
+        // Add a resource for http consumption
+        MediaResource http_res = new MediaResource.from_resource ("primary_http",
+                                                                  primary_res);
+        http_res.uri = ""; // The URI needs to be assigned by the MediaServer
+        resources.add (http_res);
+
+        var list = new GLib.List<GstTranscoder> ();        
+        foreach (var transcoder in transcoders) {
+            if (transcoder.get_distance (item) != uint.MAX) {
+                list.append (transcoder);
+            }
+        }
+        list.sort_with_data( (transcoder_1, transcoder_2) => {
+                                 return (int) ( transcoder_1.get_distance (item)
+                                                - transcoder_2.get_distance (item) );
+                             } );
+
+        // Put all Transcoders in the list according to their sorted rank
+        foreach (var transcoder in list) {
+            MediaResource res = transcoder.get_resource_for_item (item);
+            if (res != null) 
+                resources.add (res);
+        }
+
+        // Put the primary resource as most-preferred (front of the list)
+        resources.add (primary_res);
+
+        return resources;
+    }
+
+    public override DataSource? create_data_source_for_resource ( MediaObject object,
+                                                                  MediaResource resource) {
+        if (! (object is MediaFileItem)) {
+            warning ("Can only process file-based MediaObjects (MediaFileItems)");
+            return null;
+        }
+        var item = object as MediaFileItem; 
+
+        // For MediaFileItems, uri 0 is the file URI referring directly to the content
+        string source_uri = item.uris.get (0);
+        debug ("creating data source for %s", source_uri);
+
+        try {
+            DataSource ds = new GstDataSource (source_uri, resource);
+            debug ("MediaResource %s, profile %s, mime_type %s", resource.get_name (),
+                   resource.dlna_profile, resource.mime_type);
+            if (resource.dlna_conversion == DLNAConversion.TRANSCODED) {
+                foreach (var transcoder in transcoders) {
+                    if (transcoder.name == resource.get_name()) {
+                        debug ("creating data source from transcoder %s (profile %s)",
+                                transcoder.name, transcoder.dlna_profile );
+                        ds = transcoder.create_source (item, ds);
+                        break;
+                    }
+                }
+            }
+            return ds;
+        } catch (Error error) {
+            warning (_("Failed to create GStreamer data source for %s: %s"),
+                     source_uri,
+                     error.message);
+
+            return null;
+        }
     }
 
-    public override DataSource? create_data_source (string uri) {
+    public override DataSource? create_data_source_for_uri (string source_uri) {
         try {
-            return new GstDataSource (uri);
+            debug("creating data source for %s", source_uri);
+            DataSource ds = new GstDataSource (source_uri, null);
+            return ds;
         } catch (Error error) {
             warning (_("Failed to create GStreamer data source for %s: %s"),
-                     uri,
+                     source_uri,
                      error.message);
 
             return null;
diff --git a/src/media-engines/gstreamer/rygel-gst-sink.vala b/src/media-engines/gstreamer/rygel-gst-sink.vala
index acdaefe..6999db4 100644
--- a/src/media-engines/gstreamer/rygel-gst-sink.vala
+++ b/src/media-engines/gstreamer/rygel-gst-sink.vala
@@ -43,7 +43,7 @@ internal class Rygel.GstSink : Sink {
     private Mutex buffer_mutex = Mutex ();
     private Cond buffer_condition = Cond ();
     private unowned DataSource source;
-    private HTTPSeek offsets;
+    private HTTPSeekRequest offsets;
 
     private bool frozen;
 
@@ -56,7 +56,7 @@ internal class Rygel.GstSink : Sink {
         add_pad_template (template);
     }
 
-    public GstSink (DataSource source, HTTPSeek? offsets) {
+    public GstSink (DataSource source, HTTPSeekRequest? offsets) {
         this.bytes_sent = 0;
         this.max_bytes = int64.MAX;
         this.source = source;
@@ -69,8 +69,8 @@ internal class Rygel.GstSink : Sink {
         this.frozen = false;
 
         if (this.offsets != null) {
-            if (this.offsets.seek_type == HTTPSeekType.BYTE) {
-                this.max_bytes = this.offsets.length;
+            if (this.offsets is HTTPByteSeekRequest) {
+                this.max_bytes = (this.offsets as HTTPByteSeekRequest).total_size;
             }
         }
 
diff --git a/src/media-engines/gstreamer/rygel-gst-transcoder.vala b/src/media-engines/gstreamer/rygel-gst-transcoder.vala
index 649785e..f56243f 100644
--- a/src/media-engines/gstreamer/rygel-gst-transcoder.vala
+++ b/src/media-engines/gstreamer/rygel-gst-transcoder.vala
@@ -1,10 +1,12 @@
 /*
  * Copyright (C) 2009-2012 Nokia Corporation.
  * Copyright (C) 2012 Intel Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
  *                               <zeeshan.ali@nokia.com>
  *         Jens Georg <jensg@openismus.com>
+ *         Prasanna Modem <prasanna@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -32,10 +34,16 @@ public errordomain Rygel.GstTranscoderError {
 }
 
 /**
- * The base Transcoder class. Each implementation derives from it and must
- * implement get_distance and get_encoding_profile methods.
+ * The base Transcoder class used by gstreamer media engine.
+ * Each implementation derives from it and must
+ * implement get_resources_for_item and get_encoding_profile methods.
  */
-internal abstract class Rygel.GstTranscoder : Rygel.Transcoder {
+public abstract class Rygel.GstTranscoder : GLib.Object {
+    public string name { get; construct; }
+    public string mime_type { get; construct; }
+    public string dlna_profile { get; construct; }
+    public string extension { get; construct; }
+
     public string preset { get;
                            protected set;
                            default =  DEFAULT_ENCODING_PRESET; }
@@ -49,10 +57,12 @@ internal abstract class Rygel.GstTranscoder : Rygel.Transcoder {
 
     private bool link_failed;
 
-    public GstTranscoder (string mime_type,
+    public GstTranscoder (string name,
+                          string mime_type,
                           string dlna_profile,
                           string extension) {
-        GLib.Object (mime_type : mime_type,
+        GLib.Object (name : name,
+                     mime_type : mime_type,
                      dlna_profile : dlna_profile,
                      extension : extension);
     }
@@ -64,6 +74,47 @@ internal abstract class Rygel.GstTranscoder : Rygel.Transcoder {
     }
 
     /**
+     * Get the supported (transcoded) MediaResource for the given content item
+     *
+     * @return A MediaResources or null if the transcoder cannot
+     * transcode this media item 
+     */
+    public virtual MediaResource? get_resource_for_item (MediaFileItem item) {
+        MediaResource res = new MediaResource(this.name);
+
+        res.mime_type = this.mime_type;
+        res.dlna_profile = this.dlna_profile;
+        res.extension = this.extension;
+        res.dlna_conversion = DLNAConversion.TRANSCODED;
+        res.dlna_flags = DLNAFlags.DLNA_V15
+                         | DLNAFlags.STREAMING_TRANSFER_MODE
+                         | DLNAFlags.BACKGROUND_TRANSFER_MODE
+                         | DLNAFlags.CONNECTION_STALL;
+        // For transcoded content only support time seek           
+        res.dlna_operation = DLNAOperation.TIMESEEK;
+
+        // Retrieve the duration from primary media resource
+        if (item is AudioItem) {
+            res.duration = (item as AudioItem).duration;
+        }
+
+        return res;
+    }        
+
+    /**
+     * Gets a numeric value that gives an gives an estimate of how hard
+     * it would be for this transcoder to trancode @item to the target profile of 
+     * this transcoder.
+     *
+     * @param item the media item to calculate the distance for
+     *
+     * @return      the distance from the @item, uint.MIN if providing such a
+     *              value is impossible or uint.MAX if it doesn't make any
+     *              sense to use this transcoder for @item
+     */
+    public abstract uint get_distance (MediaFileItem item);
+
+    /**
      * Creates a transcoding source.
      *
      * @param src the media item to create the transcoding source for
@@ -71,8 +122,7 @@ internal abstract class Rygel.GstTranscoder : Rygel.Transcoder {
      *
      * @return      the new transcoding source
      */
-    public override DataSource create_source (MediaItem  item,
-                                              DataSource src) throws Error {
+    public DataSource create_source (MediaFileItem item, DataSource src) throws Error {
         // We can only link GStreamer data sources together
         assert (src is GstDataSource);
 
diff --git a/src/media-engines/gstreamer/rygel-l16-transcoder.vala b/src/media-engines/gstreamer/rygel-l16-transcoder.vala
index 538d405..063d749 100644
--- a/src/media-engines/gstreamer/rygel-l16-transcoder.vala
+++ b/src/media-engines/gstreamer/rygel-l16-transcoder.vala
@@ -1,8 +1,10 @@
 /*
  * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
  *                               <zeeshan.ali@nokia.com>
+ *         Prasanna Modem <prasanna@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -20,6 +22,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
+
 using Gst;
 using GUPnP;
 using Gee;
@@ -34,7 +37,7 @@ internal class Rygel.L16Transcoder : Rygel.AudioTranscoder {
     private const int DEPTH = 16;
     private const bool SIGNED = true;
     private const int ENDIANNESS = ByteOrder.BIG_ENDIAN;
-
+    private const string NAME = "LPCM";
     public L16Transcoder () {
         var mime_type = "audio/L" + L16Transcoder.WIDTH.to_string () +
                         ";rate=" + L16Transcoder.FREQUENCY.to_string () +
@@ -44,35 +47,16 @@ internal class Rygel.L16Transcoder : Rygel.AudioTranscoder {
                        ",channels=" + CHANNELS.to_string () +
                        ",rate=" +  FREQUENCY.to_string ();
 
-        base (mime_type,
-              "LPCM",
+        base (NAME,
+              mime_type,
+              NAME,
               0,
               AudioTranscoder.NO_CONTAINER,
               caps_str,
               "lpcm");
     }
 
-    public override DIDLLiteResource? add_resource (DIDLLiteItem     didl_item,
-                                                    MediaItem        item,
-                                                    TranscodeManager manager)
-                                                    throws Error {
-        var resource = base.add_resource (didl_item, item, manager);
-        if (resource == null) {
-            return null;
-        }
-
-        resource.sample_freq = L16Transcoder.FREQUENCY;
-        resource.audio_channels = L16Transcoder.CHANNELS;
-        resource.bits_per_sample = L16Transcoder.WIDTH;
-        // Set bitrate in bytes/second
-        resource.bitrate = L16Transcoder.FREQUENCY *
-                           L16Transcoder.CHANNELS *
-                           L16Transcoder.WIDTH / 8;
-
-        return resource;
-    }
-
-    public override uint get_distance (MediaItem item) {
+    public override uint get_distance (MediaFileItem item) {
         if (!(item is AudioItem) || item is VideoItem) {
             return uint.MAX;
         }
@@ -94,4 +78,21 @@ internal class Rygel.L16Transcoder : Rygel.AudioTranscoder {
 
         return distance;
     }
+
+    public override MediaResource? get_resource_for_item (MediaFileItem item) {
+        var resource = base.get_resource_for_item (item);
+        if (resource == null) {
+            return null;
+        }
+
+        resource.sample_freq = L16Transcoder.FREQUENCY;
+        resource.audio_channels = L16Transcoder.CHANNELS;
+        resource.bits_per_sample = L16Transcoder.WIDTH;
+        // Set bitrate in bytes/second
+        resource.bitrate = L16Transcoder.FREQUENCY *
+                           L16Transcoder.CHANNELS *
+                           L16Transcoder.WIDTH / 8;
+
+        return resource;
+    }
 }
diff --git a/src/media-engines/gstreamer/rygel-mp2ts-transcoder.vala b/src/media-engines/gstreamer/rygel-mp2ts-transcoder.vala
index 05c5a2b..763a329 100644
--- a/src/media-engines/gstreamer/rygel-mp2ts-transcoder.vala
+++ b/src/media-engines/gstreamer/rygel-mp2ts-transcoder.vala
@@ -1,8 +1,10 @@
 /*
  * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
  *                               <zeeshan.ali@nokia.com>
+ *         Prasanna Modem <prasanna@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -20,6 +22,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
+
 using Gst;
 using GUPnP;
 
@@ -59,7 +62,8 @@ internal class Rygel.MP2TSTranscoder : Rygel.VideoTranscoder {
     private MP2TSProfile profile;
 
     public MP2TSTranscoder (MP2TSProfile profile) {
-        base ("video/mpeg",
+        base (PROFILES[profile],
+              "video/mpeg",
               PROFILES[profile],
               AUDIO_BITRATE,
               VIDEO_BITRATE,
@@ -74,23 +78,7 @@ internal class Rygel.MP2TSTranscoder : Rygel.VideoTranscoder {
         this.profile = profile;
     }
 
-    public override DIDLLiteResource? add_resource (DIDLLiteItem     didl_item,
-                                                    MediaItem        item,
-                                                    TranscodeManager manager)
-                                                    throws Error {
-        var resource = base.add_resource (didl_item, item, manager);
-        if (resource == null) {
-            return null;
-        }
-
-        resource.width = WIDTH[this.profile];
-        resource.height = HEIGHT[this.profile];
-        resource.bitrate = (VIDEO_BITRATE + AUDIO_BITRATE) * 1000 / 8;
-
-        return resource;
-    }
-
-    public override uint get_distance (MediaItem item) {
+    public override uint get_distance (MediaFileItem item) {
         if (!(item is VideoItem)) {
             return uint.MAX;
         }
@@ -112,4 +100,17 @@ internal class Rygel.MP2TSTranscoder : Rygel.VideoTranscoder {
 
         return distance;
     }
+
+    public override MediaResource? get_resource_for_item (MediaFileItem item) {
+        var resource = base.get_resource_for_item(item);
+        if (resource == null) {
+            return null;
+        }
+
+        resource.width = WIDTH[this.profile];
+        resource.height = HEIGHT[this.profile];
+        resource.bitrate = (VIDEO_BITRATE + AUDIO_BITRATE) * 1000 / 8;
+
+        return resource;
+    }
 }
diff --git a/src/media-engines/gstreamer/rygel-mp3-transcoder.vala b/src/media-engines/gstreamer/rygel-mp3-transcoder.vala
index ecbdd45..d2a327d 100644
--- a/src/media-engines/gstreamer/rygel-mp3-transcoder.vala
+++ b/src/media-engines/gstreamer/rygel-mp3-transcoder.vala
@@ -1,8 +1,10 @@
 /*
  * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
  *                               <zeeshan.ali@nokia.com>
+ *         Prasanna Modem <prasanna@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -20,6 +22,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
+
 using Gst;
 using GUPnP;
 using Gee;
@@ -30,10 +33,11 @@ using Gee;
 internal class Rygel.MP3Transcoder : Rygel.AudioTranscoder {
     public const int BITRATE = 128;
     private const string FORMAT = "audio/mpeg,mpegversion=1,layer=3";
-
+    private const string NAME = "MP3";
     public MP3Transcoder () {
-        base ("audio/mpeg",
-              "MP3",
+        base (NAME,
+              "audio/mpeg",
+              NAME,
               BITRATE,
               AudioTranscoder.NO_CONTAINER,
               FORMAT,
diff --git a/src/media-engines/gstreamer/rygel-video-transcoder.vala b/src/media-engines/gstreamer/rygel-video-transcoder.vala
index 2863917..b318399 100644
--- a/src/media-engines/gstreamer/rygel-video-transcoder.vala
+++ b/src/media-engines/gstreamer/rygel-video-transcoder.vala
@@ -1,7 +1,9 @@
 /*
  * Copyright (C) 2011 Nokia Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Jens Georg <jensg@openismus.com>
+ *         Prasanna Modem <prasanna@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -19,6 +21,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
+
 using Gst;
 using Gst.PbUtils;
 using GUPnP;
@@ -26,12 +29,13 @@ using GUPnP;
 /**
  * Base class for all transcoders that handle video.
  */
-internal class Rygel.VideoTranscoder : Rygel.AudioTranscoder {
+internal abstract class Rygel.VideoTranscoder : Rygel.AudioTranscoder {
     private int video_bitrate;
     private Caps video_codec_format;
     private Caps video_restrictions = null;
 
-    public VideoTranscoder (string  content_type,
+    public VideoTranscoder (string  name,
+                            string  content_type,
                             string  dlna_profile,
                             int     audio_bitrate,
                             int     video_bitrate,
@@ -41,7 +45,8 @@ internal class Rygel.VideoTranscoder : Rygel.AudioTranscoder {
                             string  extension,
                             string? restrictions = null) {
 
-        base.with_class (content_type,
+        base.with_class (name,
+                         content_type,
                          dlna_profile,
                          audio_bitrate,
                          container_caps,
@@ -56,25 +61,7 @@ internal class Rygel.VideoTranscoder : Rygel.AudioTranscoder {
         }
     }
 
-    public override DIDLLiteResource? add_resource (DIDLLiteItem     didl_item,
-                                                    MediaItem        item,
-                                                    TranscodeManager manager)
-                                                    throws Error {
-        var resource = base.add_resource (didl_item, item, manager);
-        if (resource == null) {
-            return null;
-        }
-
-        var video_item = item as VideoItem;
-
-        resource.width = video_item.width;
-        resource.height = video_item.height;
-        resource.bitrate = (this.video_bitrate + this.audio_bitrate) * 1000 / 8;
-
-        return resource;
-    }
-
-    public override uint get_distance (MediaItem item) {
+    public override uint get_distance (MediaFileItem item) {
         if (!(item is VideoItem)) {
             return uint.MAX;
         }
@@ -104,4 +91,19 @@ internal class Rygel.VideoTranscoder : Rygel.AudioTranscoder {
 
         return enc_container_profile;
     }
+
+    public override MediaResource? get_resource_for_item (MediaFileItem item) {    
+        var resource = base.get_resource_for_item (item);
+        if (resource == null) {
+            return null;
+        }
+
+        var video_item = item as VideoItem;
+
+        resource.width = video_item.width;
+        resource.height = video_item.height;
+        resource.bitrate = (this.video_bitrate + this.audio_bitrate) * 1000 / 8;
+
+        return resource;
+    }
 }
diff --git a/src/media-engines/gstreamer/rygel-wmv-transcoder.vala b/src/media-engines/gstreamer/rygel-wmv-transcoder.vala
index 947ee04..0b3519b 100644
--- a/src/media-engines/gstreamer/rygel-wmv-transcoder.vala
+++ b/src/media-engines/gstreamer/rygel-wmv-transcoder.vala
@@ -1,7 +1,9 @@
 /*
  * Copyright (C) 2009 Jens Georg <mail@jensge.org>.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Jens Georg <mail@jensge.org>
+ *         Prasanna Modem <prasanna@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -19,16 +21,18 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
+
 using Gst;
 using GUPnP;
 
 internal class Rygel.WMVTranscoder : Rygel.VideoTranscoder {
     private const int VIDEO_BITRATE = 1200;
     private const int AUDIO_BITRATE = 64;
-
+    private const string NAME = "WMVHIGH_FULL";
     public WMVTranscoder () {
-        base ("video/x-ms-wmv",
-              "WMVHIGH_FULL",
+        base (NAME,
+              "video/x-ms-wmv",
+              NAME,
               AUDIO_BITRATE,
               VIDEO_BITRATE,
               "video/x-ms-asf,parsed=true",
diff --git a/src/media-engines/simple/rygel-simple-data-source.vala b/src/media-engines/simple/rygel-simple-data-source.vala
index 3f66941..98026c2 100644
--- a/src/media-engines/simple/rygel-simple-data-source.vala
+++ b/src/media-engines/simple/rygel-simple-data-source.vala
@@ -1,7 +1,9 @@
 /*
  * Copyright (C) 2012 Intel Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Jens Georg <jensg@openismus.com>
+ *         Craig Pratt <craig@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -38,7 +40,6 @@ internal class Rygel.SimpleDataSource : DataSource, Object {
     private Posix.off_t last_byte = 0;
     private bool frozen = false;
     private bool stop_thread = false;
-    private HTTPSeek offsets = null;
 
     public SimpleDataSource (string uri) {
         debug ("Creating new data source for %s", uri);
@@ -49,17 +50,39 @@ internal class Rygel.SimpleDataSource : DataSource, Object {
         this.stop ();
     }
 
-    public void start (HTTPSeek? offsets) throws Error {
-        if (offsets != null) {
-            if (offsets.seek_type == HTTPSeekType.TIME) {
-                throw new DataSourceError.SEEK_FAILED
-                                        (_("Time-based seek not supported"));
+    public Gee.List<HTTPResponseElement> ? preroll (HTTPSeekRequest? seek_request,
+                                                    PlaySpeedRequest? playspeed_request)
+       throws Error {
+        var response_list = new Gee.ArrayList<HTTPResponseElement> ();
 
+        if (seek_request != null) {
+            if (!(seek_request is HTTPByteSeekRequest)) {
+                throw new DataSourceError.SEEK_FAILED
+                                        (_("Only byte-based seek supported"));
             }
+
+            var byte_seek = seek_request as HTTPByteSeekRequest;
+            this.first_byte = (Posix.off_t) byte_seek.start_byte;
+            this.last_byte = (Posix.off_t) (byte_seek.end_byte + 1);
+            debug ("Processing byte seek request for bytes %lld-%lld of %s",
+                    byte_seek.start_byte, byte_seek.end_byte, this.uri);
+            var seek_response = new HTTPByteSeekResponse.from_request (byte_seek);
+            // Response will just return what was in the request
+            response_list.add (seek_response);
+        } else {
+            this.first_byte = 0;
+            this.last_byte = 0; // Indicates the entire file
         }
 
-        this.offsets = offsets;
+        if (playspeed_request != null) {
+            throw new DataSourceError.PLAYSPEED_FAILED
+                                    (_("Playspeed not supported"));
+        }
+
+        return response_list;
+    }
 
+    public void start () throws Error {
         debug ("Starting data source for uri %s", this.uri);
 
         // TODO: Convert to use a thread pool
@@ -112,11 +135,7 @@ internal class Rygel.SimpleDataSource : DataSource, Object {
                                           Posix.strerror (Posix.errno));
             }
 
-            if (this.offsets != null) {
-                this.first_byte = (Posix.off_t) this.offsets.start;
-                this.last_byte = (Posix.off_t) this.offsets.stop + 1;
-            } else {
-                this.first_byte = 0;
+            if (this.last_byte == 0) {
                 this.last_byte = Posix.lseek (fd, 0, Posix.SEEK_END);
                 Posix.lseek (fd, 0, Posix.SEEK_SET);
             }
diff --git a/src/media-engines/simple/rygel-simple-media-engine.vala b/src/media-engines/simple/rygel-simple-media-engine.vala
index 512a9f2..5281124 100644
--- a/src/media-engines/simple/rygel-simple-media-engine.vala
+++ b/src/media-engines/simple/rygel-simple-media-engine.vala
@@ -1,7 +1,9 @@
 /*
  * Copyright (C) 2012 Intel Corporation.
+ * Copyright (C) 2013 Cable Television Laboratories, Inc.
  *
  * Author: Jens Georg <jensg@openismus.com>
+ *         Craig Pratt <craig@ecaspia.com>
  *
  * This file is part of Rygel.
  *
@@ -20,11 +22,13 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+using GUPnP;
+
 /**
  * The simple media engine does not use GStreamer or any other
  * multimedia framework. Therefore its capabilities are limited.
  *
- * It does not support transcoding - get_transcoders() returns null.
+ * It does not support transcoding - get_resources() returns null.
  * Also, its RygelSimpleDataSource does not support time-base seeking.
  */
 internal class Rygel.SimpleMediaEngine : MediaEngine {
@@ -32,19 +36,62 @@ internal class Rygel.SimpleMediaEngine : MediaEngine {
 
     public SimpleMediaEngine () { }
 
-    public override unowned List<DLNAProfile> get_dlna_profiles () {
+    public override unowned List<DLNAProfile> get_dlna_profiles() {
         return this.profiles;
     }
 
-    public override unowned List<Transcoder>? get_transcoders () {
-        return null;
+    public override async Gee.List<MediaResource> ? get_resources_for_item
+                                                        (MediaObject object) {
+        if (! (object is MediaFileItem)) {
+            warning ("Can only process file-based MediaObjects (MediaFileItems)");
+            return null;
+        }
+
+        var item = object as MediaFileItem; 
+
+        // For MediaFileItems, uri 0 is the file URI referring directly to the content
+        string source_uri = item.uris.get (0);
+        if (!source_uri.has_prefix ("file://")) {
+            warning ("Can't process non-file uri " + source_uri);
+        }
+
+        debug ("get_resources_for_item (%s)", source_uri);
+
+        Gee.List<MediaResource> resources = new Gee.ArrayList<MediaResource> ();
+
+        var primary_res = item.get_primary_resource ();
+
+        // The SimpleMediaEngine supports only byte-based seek
+        primary_res.dlna_operation = GUPnP.DLNAOperation.RANGE;
+
+        // Add a resource for http consumption (as SimpleMediaEngine can handle http)
+        MediaResource http_res = new MediaResource.from_resource ("primary_http",
+                                                                  primary_res);
+        http_res.uri = ""; // The URI needs to be assigned by the MediaServer
+        resources.add (http_res);
+
+        resources.add (primary_res);
+
+        return resources;
     }
 
-    public override DataSource? create_data_source (string uri) {
-        if (!uri.has_prefix ("file://")) {
+    public override DataSource? create_data_source_for_resource (MediaObject object,
+                                                                 MediaResource resource) {
+        if (! (object is MediaFileItem)) {
+            warning ("Can only process file-based MediaObjects (MediaFileItems)");
             return null;
         }
 
+        // For MediaFileItems, uri 0 is the file URI referring directly to the content
+        string source_uri = object.uris.get (0);
+        return new SimpleDataSource (source_uri);
+    }
+
+    public override DataSource? create_data_source_for_uri (string uri) {
+        if (!uri.has_prefix ("file://")) {
+            return null;
+        }
+        debug ("creating data source for %s", uri);
         return new SimpleDataSource (uri);
     }
 }
