Files
vova 64a337ffe8 Improve LibVLC stability and add external playback host
- Add LibVLCManager singleton for safer LibVLC lifetime management
- Introduce VlcHostClient and VlcHost.exe for external playback via JSON commands
- Enhance VideoPlayer with error recovery and dependency property for SourceUrl
- Implement IDisposable in ProgramsData and ViewModels for better cleanup
- Update NuGet packages: LibVLCSharp to 3.9.6, System.Reactive to 6.1.0
- Add robust error handling and resource disposal throughout
- Improve program guide handling in PlayerViewModel
2026-04-10 14:29:00 +03:00

130 lines
3.4 KiB
C#

using System;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using LibVLCSharp.Shared;
class Command
{
public string cmd { get; set; }
public string url { get; set; }
}
class Response
{
public string status { get; set; }
public string message { get; set; }
}
class Program
{
static LibVLC _libVlc;
static MediaPlayer _player;
static Media _media;
static async Task<int> Main(string[] args)
{
Core.Initialize();
// create libvlc with conservative options to reduce native crashes
_libVlc = new LibVLC(new[] { "--ignore-config", "--no-osd", "--avcodec-hw=none", "--network-caching=3000", "--http-reconnect" });
using var stdin = Console.OpenStandardInput();
using var reader = new StreamReader(stdin);
string line;
// write banner
Console.Out.WriteLine(JsonSerializer.Serialize(new Response { status = "ready", message = "VlcHost ready" }));
Console.Out.Flush();
while ((line = await reader.ReadLineAsync()) != null)
{
if (string.IsNullOrWhiteSpace(line)) continue;
try
{
var cmd = JsonSerializer.Deserialize<Command>(line);
if (cmd == null)
{
WriteResponse("error", "invalid command");
continue;
}
switch (cmd.cmd?.ToLowerInvariant())
{
case "play":
await CmdPlay(cmd.url);
break;
case "stop":
CmdStop();
break;
case "ping":
WriteResponse("ok", "pong");
break;
case "exit":
WriteResponse("ok", "exiting");
return 0;
default:
WriteResponse("error", "unknown command");
break;
}
}
catch (Exception ex)
{
WriteResponse("error", ex.Message);
}
}
return 0;
}
static async Task CmdPlay(string url)
{
try
{
if (string.IsNullOrWhiteSpace(url))
{
WriteResponse("error", "url empty");
return;
}
CmdStop();
_media = new Media(_libVlc, url, FromType.FromLocation);
_player = new MediaPlayer(_libVlc);
_player.Play(_media);
WriteResponse("ok", "playing");
}
catch (Exception ex)
{
WriteResponse("error", ex.Message);
}
}
static void CmdStop()
{
try
{
if (_player != null)
{
_player.Stop();
try { _media?.Dispose(); } catch { }
try { _player.Dispose(); } catch { }
_player = null;
_media = null;
}
WriteResponse("ok", "stopped");
}
catch (Exception ex)
{
WriteResponse("error", ex.Message);
}
}
static void WriteResponse(string status, string message)
{
var resp = new Response { status = status, message = message };
var json = JsonSerializer.Serialize(resp);
Console.Out.WriteLine(json);
Console.Out.Flush();
}
}