Introduction
This lightweight little DLNA server is able to stream files to your network devices ("Smart TV's) and will use byte-ranges if the device offers this option so that the current playing position of the movie or sound can be forwarded during playback.
One off the easiest ways to host movies for playing across the network is to use a virtual directory in window IIS-Server and then send the Url of the movie/sound file to the DLNA device but this method becomes a little bloated and is overkill.
This little service replaces the host service offered by windows IIS-Server and simply services the request from devices such as smart TV's and is not a DLNA-Player as such but has been tested with VLC-Player and works fine with Samsung, LG, Sony Smart TV's
What's in the files
The projects was written using Visual Studio 2010 with C# and I have included a noddy user-interface form in the download to get you started that will allow you to test the service which includes the core component "MediaService.cs" and a small helper class "Helper.cs" that can be used to create your own full blown media player or you may decide to use this code as a simple web-server in other projects.
Starting the service
The service needs the ip-address and port number to listing on and the root location of the file system that contains the media files which could be on the local machine or a network drive that is connected to the local network.
private MediaServer MServer = null;
MServer = new MediaServer(this.TxtIP.Text, int.Parse(this.TxtPort.Text), this.TxtMediaPath.Text);
MServer.Start();
if (MServer != null) MServer.Stop();
When the service is started a new thread is used to listen for incoming requests in a loop and if the request is just for "HEAD
" data then the file is opened to retrieve the size of the file and the data then gets returned to the calling client (Smart TV) using the main server thread.
private void SendHeadData(Socket Soc, string FileName)
{
FileInfo FInfo = new FileInfo(FileName);
if (!FInfo.Exists)
{
Soc.Close();
this.TempClient = null;
return;
}
string ContentType = GetContentType(FileName);
string Reply = "HTTP/1.1 200 OK" + Environment.NewLine + "Server: VLC" + Environment.NewLine + "Content-Type: " + ContentType + Environment.NewLine;
Reply += "Last-Modified: " + GMTTime(DateTime.Now.AddYears(-1).AddDays(-7)) + Environment.NewLine;
Reply += "Date: " + GMTTime(DateTime.Now) + Environment.NewLine;
if (!IsMusicOrImage(FileName)) Reply += "Accept-Ranges: bytes" + Environment.NewLine;
Reply += "Content-Length: " + FInfo.Length + Environment.NewLine;
Reply += "Connection: close" + Environment.NewLine + Environment.NewLine;
Soc.Send(UTF8Encoding.UTF8.GetBytes(Reply), SocketFlags.None);
Soc.Close();
this.TempClient = null;
}
If on the other hand the request are for the actual data then a new thread is used to service the request so that the main thread can listen for other requests that might soon arrive.
Code below shows how chunks of data are sent back to the calling client that use a Byte-Range in the request for streaming the data a bit at a time.
private string ContentString(long Range, string ContentType, long FileLength)
{
string Reply = "";
Reply = "HTTP/1.1 206 Partial Content" + Environment.NewLine + "Server: VLC" + Environment.NewLine + "Content-Type: " + ContentType + Environment.NewLine;
Reply += "Accept-Ranges: bytes" + Environment.NewLine;
Reply += "Date: " + GMTTime(DateTime.Now) + Environment.NewLine;
if (Range == 0)
{
Reply += "Content-Length: " + FileLength + Environment.NewLine;
Reply += "Content-Range: bytes 0-" + (FileLength - 1) + "/" + FileLength + Environment.NewLine;
}
else
{
Reply += "Content-Length: " + (FileLength - Range) + Environment.NewLine;
Reply += "Content-Range: bytes " + Range + "-" + (FileLength - 1) + "/" + FileLength + Environment.NewLine;
}
return Reply + Environment.NewLine;
}
private void StreamMovie()
{
ClientCount++;
long ChunkSize = 500000;
long Range = TempRange;
long BytesSent = 0;
long ByteToSend = 1;
string FileName = TempFileName.ToLower();
string ContentType = GetContentType(FileName);
Socket Client = this.TempClient;
this.TempClient = null;
if (LastFileName != FileName)
{
if (!File.Exists(FileName)) { ClientCount--; Client.Close(); return; }
if (FS != null) FS.Close();
FileInfo FInfo = new FileInfo(FileName);
LastFileLength = FInfo.Length;
FS = new FileStream(FileName, FileMode.Open);
LastFileName = FileName;
}
string Reply = ContentString(Range, ContentType, LastFileLength);
Client.Send(UTF8Encoding.UTF8.GetBytes(Reply), SocketFlags.None);
byte[] Buf = new byte[ChunkSize];
if (FS.CanSeek)
FS.Seek(Range, SeekOrigin.Begin);
BytesSent = Range;
while (this.Running && Client.Connected && ByteToSend > 0)
{
LoopCount++;
ByteToSend = LastFileLength - BytesSent;
if (ByteToSend > ChunkSize) ByteToSend = ChunkSize;
long BytesLeftToSend = LastFileLength - BytesSent;
if (BytesSent + ChunkSize > LastFileLength)
ChunkSize = LastFileLength - BytesSent;
Buf = new byte[ByteToSend];
FS.Read(Buf, 0, Buf.Length);
BytesSent += Buf.Length;
if (Client.Connected)
{
try { Client.Send(Buf); Thread.Sleep(100); }
catch { ByteToSend = 0; }
}
}
if (!this.Running) { try { FS.Close(); FS = null; } catch { ;} }
Client.Close();
ClientCount--;
}
Testing it works
See http://www.codeproject.com/Articles/893791/DLNA-made-easy-with-Play-To-from-any-device if you are buillding a media player that will work with this media-server or test out code by using VLC-Player and then clicking media/open netowork stream and then enter the Url that should look a something like hxxp://192.168.1.10:9090/MyMovie.avi
Whats Next !
Over the years I have managed to collect quite a wide range of music but often I removed or lost the album-artwork that came with the sound tracks but with disk space being cheap these days and the invent of DLNA device I now find it is nice to look at something on the TV whilst the music is playing.
The next part to this project is a bit of code that reads the "Artist" and "Album" name from .Mp3 files and then use a well known search engine to find the album-art images that will then download these images to my network storage device so they can later be sent to the TV to be displayed as music is playing.
Edit to add
Just added the option of streaming Youtube video's to the TV's screen but had to build a Youtube downloader that you can view here http://www.codeproject.com/Articles/1081335/Youtube-downloader-in-one-easy-class