// Spludlow Software // Copyright © Samuel P. Ludlow 2020 All Rights Reserved // Distributed under the terms of the GNU General Public License version 3 // Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE // https://www.spludlow.co.uk/LICENCE.TXT // The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission // v1.14 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; using System.Diagnostics; namespace Spludlow { /// /// Some methods to spwan VLC for tuning and streaming of DVB /// /// NOTE: VLC Version 3 is broken please use 2.2.8. Make sure you use the x64 version /// /// When a string is returned then this is the command required to start the VLC client /// Only supports DVB-T /// Add vlc to firewall "C:\Program Files\VideoLAN\VLC\vlc.exe" /// public class VLC { private static string ProgramPath = @"C:\Program Files\VideoLAN\VLC\vlc.exe"; public static void StartRecording(string host, string filename, int duration, int frequency, int serviceId) { Spludlow.Call.Now(host, "Spludlow", "Spludlow.VLC", "StartRecording", new object[] { filename, duration, frequency, serviceId }); } public static void StartRecording(string filename, int duration, int frequency, int serviceId) { Stop(); StringBuilder text = new StringBuilder(); // ps not ts ? keep filename at ts! text.Append("--play-and-exit --run-time=@Duration -I=dummy --sout=\"#duplicate{dst=std{access=file,mux=ps,dst='@Filename'},select='program=@Programme'}\" dvb-t://frequency=@Frequency"); text.Replace("@Duration", duration.ToString()); text.Replace("@Filename", filename); text.Replace("@Programme", serviceId.ToString()); text.Replace("@Frequency", frequency.ToString()); Start(text.ToString()); } public static string StartServer(int frequency, int serviceId, int mode, string tunerHost, string edgeHost, string clientAddress, string publicAddress, bool clientZoom, bool clientInterlace, decimal scale) { // Can be configured to start VLC on remote machine that contains the DVB card then stream to client, not fully tested but did have it working. // Mode 0 will only work when browsing from a machine with a tuner card (web may still be runnig elsewhere) // Mode // 0 Local Tuner Tuner:Client // 1 UDP Tuner:UDP(L) -> UDP(L/P):Client // 2 Direct TCP Tuner:TCP(L) -> TCP(L):Client // prefer public?, use firewall address? // TCP // L - L // P - P use public // L - P use firewall address // L - LP - P use public on router // L - L - P use firewall address int portNumber = 32190; string transcode = ""; if (scale != 1.0M) { transcode = "transcode{vcodec=mp4v,scale=" + scale + "}:"; clientInterlace = false; clientZoom = false; } string clientParamters = null; string tunerParameters = null; switch (mode) { case 0: if (scale == 1.0M) clientParamters = "dvb-t://frequency=" + frequency + " :program=" + serviceId; else clientParamters = "dvb-t://frequency=" + frequency + " --sout=\"#duplicate{dst='" + transcode + "display',select='program=" + serviceId + "'}\""; break; case 1: tunerParameters = "dvb-t://frequency=" + frequency + " --sout=\"#duplicate{dst='" + transcode + "rtp{mux=ts,dst=" + clientAddress + ",port=" + portNumber + "}',select='program=" + serviceId + "'}\""; clientParamters = "rtp://" + clientAddress + ":" + portNumber; break; case 2: string[] tunerAddresses = Spludlow.Net.IP.UnicastAddresses(tunerHost); tunerAddresses = Spludlow.Net.IP.FilterPrivate(tunerAddresses); // Maybe public !!! if (tunerAddresses.Length < 1) throw new ApplicationException("VLC StartServer; Did not find one address: " + tunerHost + ", count:" + tunerAddresses.Length); string tunerAddress = tunerAddresses[0]; tunerParameters = "dvb-t://frequency=" + frequency + " -I=dummy --sout=\"#duplicate{dst='" + transcode + "standard{access=http,mux=ts,dst=" + tunerAddress + ":" + portNumber + "}',select='program=" + serviceId + "'}\""; clientParamters = "http://" + tunerAddress + ":" + portNumber; break; } if (mode > 0) { Stop(tunerHost); if (tunerParameters != null) { Start(tunerHost, tunerParameters); } } if (clientZoom == true) clientParamters += " --zoom 2"; if (clientInterlace == true) clientParamters += " --deinterlace 1 --deinterlace-mode yadif2x"; return "\"" + ProgramPath + "\" " + clientParamters; } public static string StartTunerServer(int frequency, int serviceId, string ipAddress, int portnumber) { Stop(); System.Threading.Thread.Sleep(1000); StringBuilder text = new StringBuilder(); text.Append("dvb-t://frequency=@Frequency -I=dummy --sout=\"#duplicate{dst=standard{access=http,mux=ts,dst=@Address:@PortNumber},select='program=@Programme'}\""); text.Replace("@Address", ipAddress); text.Replace("@PortNumber", portnumber.ToString()); text.Replace("@Programme", serviceId.ToString()); text.Replace("@Frequency", frequency.ToString()); Start(text.ToString()); return "\"" + ProgramPath + "\" http://" + ipAddress + ":" + portnumber; } public static void Start(string host, string arguments) { Spludlow.Call.Now(host, "Spludlow", "Spludlow.VLC", "Start", new object[] { arguments }); } public static void Start(string arguments) { Process.Start(ProgramPath, arguments); Spludlow.Log.Report("VLC; Started:\t" + ProgramPath + "\t" + arguments); } public static void Stop(string host) { Spludlow.Call.Now(host, "Spludlow", "Spludlow.VLC", "Stop"); } public static void Stop() { Process[] processes = Process.GetProcessesByName("vlc"); foreach (Process process in processes) { try { process.Kill(); process.WaitForExit(); // timeout !!!!!! Spludlow.Log.Report("VLC; Stopped:\t" + process.ProcessName); } catch (Exception ee) { string userName = "n/a"; if (process.StartInfo != null && process.StartInfo.UserName != null) userName = process.StartInfo.UserName; Spludlow.Log.Warning("VLC; Not Stopped: " + process.ProcessName + ", " + userName, ee); } } } } }