 ...tended.Applications.PowerSchedulerPlugin.csproj |   2 +-
 .../TvServerPlugin.cs                              |   4 +-
 .../MPExtended.Installers.Service/Filesystem.wxs   |   1 +
 Libraries/MPExtended.Libraries.Service/WCFUtil.cs  |  16 +++
 .../Code/ImageMediaSource.cs                       |  12 +-
 .../MPExtended.Services.StreamingService.csproj    |   1 +
 .../Transcoders/Direct.cs                          | 123 ++++++++++++++++++++-
 .../Units/InputUnit.cs                             |  11 +-
 .../MPExtended.Services.TVAccessService.csproj     |   4 +
 9 files changed, 161 insertions(+), 13 deletions(-)

diff --git a/Applications/MPExtended.Applications.PowerSchedulerPlugin/MPExtended.Applications.PowerSchedulerPlugin.csproj b/Applications/MPExtended.Applications.PowerSchedulerPlugin/MPExtended.Applications.PowerSchedulerPlugin.csproj
index 383c73f2..8aeb2be7 100644
--- a/Applications/MPExtended.Applications.PowerSchedulerPlugin/MPExtended.Applications.PowerSchedulerPlugin.csproj
+++ b/Applications/MPExtended.Applications.PowerSchedulerPlugin/MPExtended.Applications.PowerSchedulerPlugin.csproj
@@ -10,7 +10,7 @@
     <AppDesignerFolder>Properties</AppDesignerFolder>
     <RootNamespace>MPExtended.Applications.PowerSchedulerPlugin</RootNamespace>
     <AssemblyName>MPExtended.Applications.PowerSchedulerPlugin</AssemblyName>
-    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
     <TargetFrameworkProfile>
     </TargetFrameworkProfile>
diff --git a/Applications/MPExtended.Applications.PowerSchedulerPlugin/TvServerPlugin.cs b/Applications/MPExtended.Applications.PowerSchedulerPlugin/TvServerPlugin.cs
index ae5fced7..8fd8b169 100644
--- a/Applications/MPExtended.Applications.PowerSchedulerPlugin/TvServerPlugin.cs
+++ b/Applications/MPExtended.Applications.PowerSchedulerPlugin/TvServerPlugin.cs
@@ -71,7 +71,7 @@ public void Start(IController controller)
             {
                 Log.Debug("Starting and registering MPExtended powerhandler");
                 handler = new PowerHandler();
-                PowerScheduler.Instance.Register(handler);
+                TvEngine.PowerScheduler.PowerScheduler.Instance.Register(handler);
             }
             catch (Exception ex)
             {
@@ -84,7 +84,7 @@ public void Stop()
             try
             {
                 Log.Debug("Removing MPExtended powerhandler");
-                PowerScheduler.Instance.Unregister(handler);
+                TvEngine.PowerScheduler.PowerScheduler.Instance.Unregister(handler);
             }
             catch (Exception ex)
             {
diff --git a/Installers/MPExtended.Installers.Service/Filesystem.wxs b/Installers/MPExtended.Installers.Service/Filesystem.wxs
index 060c1a90..dee69124 100644
--- a/Installers/MPExtended.Installers.Service/Filesystem.wxs
+++ b/Installers/MPExtended.Installers.Service/Filesystem.wxs
@@ -92,6 +92,7 @@
                   <File Source="$(var.MPExtended.Services.TVAccessService.TargetDir)\TvBusinessLayer.dll" />
                   <File Source="$(var.MPExtended.Services.TVAccessService.TargetDir)\TvControl.dll" />
                   <File Source="$(var.MPExtended.Services.TVAccessService.TargetDir)\TVDatabase.dll" />
+                  <File Source="$(var.MPExtended.Services.TVAccessService.TargetDir)\Common.Utils.dll" />
                   <File Source="$(var.MPExtended.Services.TVAccessService.TargetDir)\TvLibrary.Interfaces.dll" />
                   <File Source="$(var.MPExtended.Services.TVAccessService.TargetDir)\MPExtended.Services.TVAccessService.dll" />
                   <File Source="$(var.MPExtended.Services.TVAccessService.TargetDir)\MPExtended.Services.TVAccessService.pdb" />
diff --git a/Libraries/MPExtended.Libraries.Service/WCFUtil.cs b/Libraries/MPExtended.Libraries.Service/WCFUtil.cs
index 70056968..88de19ee 100644
--- a/Libraries/MPExtended.Libraries.Service/WCFUtil.cs
+++ b/Libraries/MPExtended.Libraries.Service/WCFUtil.cs
@@ -25,6 +25,7 @@
 using System.Text;
 using MPExtended.Libraries.Service.Network;
 using MPExtended.Libraries.Service.Extensions;
+using System.Net.Mime;
 
 namespace MPExtended.Libraries.Service
 {
@@ -32,6 +33,7 @@ public static class WCFUtil
     {
         internal const string HEADER_NAMESPACE = "http://mpextended.github.com/";
         internal const string ORIGINAL_URL_HEADER = "X-Root-URL";
+        private const string ContentDisposition = "Content-Disposition";
 
         private static bool IsRestEnabled
         {
@@ -135,10 +137,24 @@ public static void SetContentLength(long length)
             {
                 // This doesn't work yet (#96)
                 WebOperationContext.Current.OutgoingResponse.ContentLength = length;
+                SetContentDisposition(disp => disp.Size = length);
                 AddHeader("X-Content-Length", length.ToString());
             }
         }
 
+        private static void SetContentDisposition(Action<ContentDisposition> dispositionAction)
+        {
+            if (WebOperationContext.Current == null)
+                return;
+
+            string contentDisposition = WebOperationContext.Current.OutgoingResponse.Headers[ContentDisposition];
+            if (string.IsNullOrEmpty(contentDisposition))
+                contentDisposition = "inline";
+            var disp = new ContentDisposition(contentDisposition);
+            dispositionAction(disp);
+            WebOperationContext.Current.OutgoingResponse.Headers[ContentDisposition] = disp.ToString();
+        }
+
 
         public static void SetContentType(string type)
         {
diff --git a/Services/MPExtended.Services.StreamingService/Code/ImageMediaSource.cs b/Services/MPExtended.Services.StreamingService/Code/ImageMediaSource.cs
index c8c28288..3cf34143 100644
--- a/Services/MPExtended.Services.StreamingService/Code/ImageMediaSource.cs
+++ b/Services/MPExtended.Services.StreamingService/Code/ImageMediaSource.cs
@@ -106,9 +106,17 @@ public override WebFileInfo GetFileInfo()
 
                 // get display name
                 int idChannel = MediaType == WebMediaType.TV || MediaType == WebMediaType.Radio ?
-                    Int32.Parse(Id) :
-                    Connections.TAS.GetRecordingById(Int32.Parse(Id)).ChannelId;
+                    Int32.Parse(Id) : Connections.TAS.GetRecordingById(Int32.Parse(Id)).ChannelId;
+
+                // get the channel, the channel may no longer exist for recording.  
                 var channel = Connections.TAS.GetChannelBasicById(idChannel);
+                if(channel == null)
+                {
+                    Log.Debug("Did not find the tv channel with id {0}", idChannel);
+                    fileInfoCache = new WebFileInfo() { Exists = false };
+                    return fileInfoCache;
+                }
+
                 string location = _logos.FindLocation(channel.Title);
                 if(location == null)
                 {
diff --git a/Services/MPExtended.Services.StreamingService/MPExtended.Services.StreamingService.csproj b/Services/MPExtended.Services.StreamingService/MPExtended.Services.StreamingService.csproj
index fa2382f2..3eb0f464 100644
--- a/Services/MPExtended.Services.StreamingService/MPExtended.Services.StreamingService.csproj
+++ b/Services/MPExtended.Services.StreamingService/MPExtended.Services.StreamingService.csproj
@@ -96,6 +96,7 @@
     <Compile Include="Transcoders\VLCManaged.cs" />
     <Compile Include="Transcoders\VLCWrapper.cs" />
     <Compile Include="Transcoders\VLCWrapperHTTPLiveStreaming.cs" />
+    <Compile Include="Units\DirectStream.cs" />
     <Compile Include="Units\FLVMetadataInjector.cs" />
     <Compile Include="Units\HTTPLiveStreamUnit.cs" />
     <Compile Include="Units\ImpersonationInputUnit.cs" />
diff --git a/Services/MPExtended.Services.StreamingService/Transcoders/Direct.cs b/Services/MPExtended.Services.StreamingService/Transcoders/Direct.cs
index 9ab25f04..1729b4b7 100644
--- a/Services/MPExtended.Services.StreamingService/Transcoders/Direct.cs
+++ b/Services/MPExtended.Services.StreamingService/Transcoders/Direct.cs
@@ -20,11 +20,17 @@
 using System.IO;
 using System.Linq;
 using System.Text;
+
+using System.ServiceModel;
+using System.ServiceModel.Web;
 using MPExtended.Libraries.Service;
 using MPExtended.Libraries.Service.Util;
 using MPExtended.Services.Common.Interfaces;
 using MPExtended.Services.StreamingService.Code;
 using MPExtended.Services.StreamingService.Interfaces;
+using System.Text.RegularExpressions;
+using System.Net;
+using Microsoft.Win32;
 
 namespace MPExtended.Services.StreamingService.Transcoders
 {
@@ -33,6 +39,20 @@ internal class Direct : ITranscoder, IRetrieveHookTranscoder
         public string Identifier { get; set; }
         public StreamContext Context { get; set; }
 
+        private static Lazy<Dictionary<string, string>> mimeDatabase = new Lazy<Dictionary<string, string>>(CreateMimeDatabase, true);
+        private static readonly string[] usedTypes = new[] { "video", "audio", "image" };
+        private static readonly Regex bytes = new Regex(@"^bytes=(\d+)(?:-(\d+)?)?$", RegexOptions.Compiled);
+
+        /// <summary>
+        /// Get from MIME-Database in Registry
+        /// </summary>
+        /// <param name="extention"></param>
+        /// <returns></returns>
+        public static bool TryGetMime(string extention, out string mime)
+        {
+            return mimeDatabase.Value.TryGetValue(extention, out mime);
+        }
+
         public string GetStreamURL()
         {
             return WCFUtil.GetCurrentRoot() + "StreamingService/stream/RetrieveStream?identifier=" + Identifier;
@@ -48,17 +68,110 @@ public void BuildPipeline()
 
         public void RetrieveStreamCalled()
         {
+
+            string mime;
+            if (!TryGetMime(Path.GetExtension(Context.Source.GetFileInfo().Name), out mime))
+                mime = "application/octet-stream";
+
+            WCFUtil.SetContentType(mime);
+            WCFUtil.AddHeader("Last-Modified", Context.Source.GetFileInfo().LastModifiedTime.ToString("r", System.Globalization.CultureInfo.InvariantCulture));
+
+            StreamLog.Info(Identifier, "*RetrieveStream Source={0}, MediaType={1}, ContenType={2}", Context.Source.GetFileInfo().Name, Context.Source.MediaType, mime);
+
             // Don't return a length when we're streaming TV, as we don't know the full length of the stream, since we are
             // reading from a timeshifting buffer. See dicussion in bug #394 and #319. 
             if (Context.Source.MediaType != WebMediaType.TV)
-                WCFUtil.SetContentLength(Context.Source.GetFileInfo().Size);
+            {
+                var stream = Context.Pipeline.GetFinalStream();
+                string range = WebOperationContext.Current.IncomingRequest.Headers["Range"];
+                if (range != null)
+                {
+                    //Test the Stream is Closed, Closed Why? WCF Close the Stream on EOF see DirectStream.cs
+                    StreamLog.Info(Identifier, "Range requested: '{0}' - can {1}Seek", range, !stream.CanSeek ? "not " : string.Empty);
+                    if (!stream.CanSeek)
+                    {
+                        WCFUtil.AddHeader("Accept-Ranges", "none");
+                        WCFUtil.SetContentLength(Context.Source.GetFileInfo().Size);
+                        return;
+                    }
+
+                    long totalLength = Context.Source.GetFileInfo().Size;
+                    long sendCount = totalLength;
+                    long start = 0L;
+                    long end = totalLength - 1;
+
+                    if (!TryGetRange(range, totalLength, ref start, ref end))
+                    {
+                        WCFUtil.SetResponseCode(HttpStatusCode.RequestedRangeNotSatisfiable);
+                        WCFUtil.AddHeader("Connection", "close");
+                        StreamLog.Debug(Identifier, "RangeNotSatisfiable: '{0}'", range);
+                        return;
+                    }
+
+                    var contentrange = string.Format("bytes {0}-{1}/{2}", start, end, totalLength);
+                    sendCount = end - start + 1;
+
+                    StreamLog.Debug(Identifier, "Range set: {0}", contentrange);
+                    StreamLog.Info(Identifier, "SeekTo: {0}", start);
+                    stream.Position = start;
+
+                    WCFUtil.AddHeader("Accept-Ranges", "bytes");
+                    WCFUtil.AddHeader("Content-Range", contentrange);
+                    WCFUtil.SetContentLength(sendCount);
+                    WCFUtil.SetResponseCode(HttpStatusCode.PartialContent);
 
-            // there has to be a better way to do this
-            object mime = RegistryReader.ReadKey(Microsoft.Win32.RegistryHive.ClassesRoot, Path.GetExtension(Context.Source.GetFileInfo().Name), "Content Type");
-            if (mime != null)
+                    return;
+                }
+            }
+
+            WCFUtil.AddHeader("Accept-Ranges", "none");
+            WCFUtil.SetContentLength(Context.Source.GetFileInfo().Size);
+
+        }
+
+        private bool TryGetRange(string range, long totalLength, ref long start, ref long end)
+        {
+            var m = bytes.Match(range);
+            if (m.Success)
             {
-                WCFUtil.SetContentType(mime.ToString());
+                if (long.TryParse(m.Groups[1].Value, out start) && start >= 0)
+                {
+                    if (m.Groups.Count != 3 || !long.TryParse(m.Groups[2].Value, out end) || end <= start || end >= totalLength)
+                    {
+                        end = totalLength - 1;
+                    }
+                    return !(start >= totalLength);
+                }
             }
+            return false;
         }
+
+        private static Dictionary<string, string> CreateMimeDatabase()
+        {
+            var mimeDatabase = new Dictionary<string, string>();
+
+            using (RegistryKey database = Registry.ClassesRoot.OpenSubKey("MIME\\Database\\Content Type"))
+            {
+                if (database != null)
+                {
+                    foreach (string mimeType in database.GetSubKeyNames().Where(mt => usedTypes.Count(ut => mt.StartsWith(ut)) > 0))
+                    {
+                        using (RegistryKey mimeKey = database.OpenSubKey(mimeType))
+                        {
+                            var extension = mimeKey.GetValue("Extension") as string;
+                            if (!string.IsNullOrWhiteSpace(extension))
+                                mimeDatabase[extension] = mimeType;
+                        }
+                    }
+                }
+            }
+
+            mimeDatabase.Add(".tsbuffer", "video/mp2ts");
+            if (!mimeDatabase.ContainsKey(".ts"))
+                mimeDatabase.Add(".ts", "video/mp2ts");
+
+            return mimeDatabase;
+        }
+
     }
 }
diff --git a/Services/MPExtended.Services.StreamingService/Units/InputUnit.cs b/Services/MPExtended.Services.StreamingService/Units/InputUnit.cs
index e9bbda79..c3cecb35 100644
--- a/Services/MPExtended.Services.StreamingService/Units/InputUnit.cs
+++ b/Services/MPExtended.Services.StreamingService/Units/InputUnit.cs
@@ -50,12 +50,14 @@ public bool Setup()
                 if (source.IndexOf(".ts.tsbuffer") != -1)
                 {
                     StreamLog.Info(identifier, "Using TsBuffer to read input");
-                    DataOutputStream = new TsBuffer(this.source);
+                    DataOutputStream = new TsBuffer(source);
                 }
                 else
                 {
                     StreamLog.Info(identifier, "Using FileStream to read input");
-                    DataOutputStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+                    var baseStram = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, short.MaxValue, FileOptions.RandomAccess);
+                    DataOutputStream = new DirectStream(baseStram, identifier);
+     //               DataOutputStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                 }
             }
             catch (Exception e)
@@ -73,7 +75,10 @@ public bool Start()
 
         public bool Stop()
         {
-            DataOutputStream.Close();
+            var directStream = DataOutputStream as DirectStream;
+            if (directStream != null)
+                directStream.Stop();
+            else DataOutputStream.Close();
             return true;
         }
     }
diff --git a/Services/MPExtended.Services.TVAccessService/MPExtended.Services.TVAccessService.csproj b/Services/MPExtended.Services.TVAccessService/MPExtended.Services.TVAccessService.csproj
index d3cce2a6..89f42996 100644
--- a/Services/MPExtended.Services.TVAccessService/MPExtended.Services.TVAccessService.csproj
+++ b/Services/MPExtended.Services.TVAccessService/MPExtended.Services.TVAccessService.csproj
@@ -36,6 +36,10 @@
     <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="Common.Utils, Version=1.6.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\Libraries\TVEngine3\Common.Utils.dll</HintPath>
+    </Reference>
     <Reference Include="Gentle.Common">
       <HintPath>..\..\Libraries\Database\Gentle.Common.dll</HintPath>
     </Reference>
