2018-10-25 19:20:23 +08:00
|
|
|
|
using Autofac;
|
|
|
|
|
using BililiveRecorder.Core;
|
|
|
|
|
using BililiveRecorder.FlvProcessor;
|
2019-01-31 14:17:38 +08:00
|
|
|
|
using CommandLine;
|
2018-12-11 00:57:40 +08:00
|
|
|
|
using Hardcodet.Wpf.TaskbarNotification;
|
2018-03-21 20:56:56 +08:00
|
|
|
|
using NLog;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.ObjectModel;
|
2018-11-02 00:40:19 +08:00
|
|
|
|
using System.IO;
|
2018-03-12 18:57:20 +08:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Windows;
|
|
|
|
|
using System.Windows.Controls;
|
|
|
|
|
using System.Windows.Input;
|
2018-11-24 23:45:08 +08:00
|
|
|
|
using System.Windows.Threading;
|
2018-03-24 09:48:06 +08:00
|
|
|
|
|
2018-03-12 18:57:20 +08:00
|
|
|
|
namespace BililiveRecorder.WPF
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Interaction logic for MainWindow.xaml
|
|
|
|
|
/// </summary>
|
|
|
|
|
public partial class MainWindow : Window
|
|
|
|
|
{
|
2018-03-21 20:56:56 +08:00
|
|
|
|
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
|
|
|
|
|
|
|
|
|
private const int MAX_LOG_ROW = 25;
|
2018-11-02 00:40:19 +08:00
|
|
|
|
private const string LAST_WORK_DIR_FILE = "lastworkdir";
|
2018-03-21 20:56:56 +08:00
|
|
|
|
|
2018-10-25 19:20:23 +08:00
|
|
|
|
private IContainer Container { get; set; }
|
|
|
|
|
private ILifetimeScope RootScope { get; set; }
|
|
|
|
|
|
2018-11-28 22:29:35 +08:00
|
|
|
|
public IRecorder Recorder { get; set; }
|
2018-03-21 20:56:56 +08:00
|
|
|
|
public ObservableCollection<string> Logs { get; set; } =
|
|
|
|
|
new ObservableCollection<string>()
|
|
|
|
|
{
|
2018-03-28 18:55:22 +08:00
|
|
|
|
"当前版本:" + BuildInfo.Version,
|
2018-03-21 20:56:56 +08:00
|
|
|
|
"网站: https://rec.danmuji.org",
|
2018-11-10 14:03:17 +08:00
|
|
|
|
"QQ群: 689636812",
|
2019-05-22 20:13:37 +08:00
|
|
|
|
"",
|
|
|
|
|
"【公告】问卷调查",
|
|
|
|
|
"如果有空的话麻烦填一下问卷调查,问卷统计结果将会影响到增删什么功能的决定。",
|
|
|
|
|
"问卷共 4 页,大约 25 题,预计用时 7 分钟。右键点击链接可以复制。谢谢。",
|
|
|
|
|
"https://wj.qq.com/s2/3740592/5e24",
|
|
|
|
|
"",
|
2018-03-21 20:56:56 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public static void AddLog(string message) => _AddLog?.Invoke(message);
|
|
|
|
|
private static Action<string> _AddLog;
|
|
|
|
|
|
2018-03-12 18:57:20 +08:00
|
|
|
|
public MainWindow()
|
|
|
|
|
{
|
2018-11-24 23:45:08 +08:00
|
|
|
|
|
|
|
|
|
_AddLog = (message) =>
|
|
|
|
|
Log.Dispatcher.BeginInvoke(
|
|
|
|
|
DispatcherPriority.DataBind,
|
|
|
|
|
new Action(() => { Logs.Add(message); while (Logs.Count > MAX_LOG_ROW) { Logs.RemoveAt(0); } })
|
|
|
|
|
);
|
2018-11-01 23:40:50 +08:00
|
|
|
|
|
2018-10-25 19:20:23 +08:00
|
|
|
|
var builder = new ContainerBuilder();
|
|
|
|
|
builder.RegisterModule<FlvProcessorModule>();
|
|
|
|
|
builder.RegisterModule<CoreModule>();
|
|
|
|
|
Container = builder.Build();
|
|
|
|
|
RootScope = Container.BeginLifetimeScope("recorder_root");
|
|
|
|
|
|
2018-11-28 22:29:35 +08:00
|
|
|
|
Recorder = RootScope.Resolve<IRecorder>();
|
2018-03-21 20:56:56 +08:00
|
|
|
|
|
2018-03-12 18:57:20 +08:00
|
|
|
|
InitializeComponent();
|
2018-03-21 20:56:56 +08:00
|
|
|
|
|
|
|
|
|
DataContext = this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Window_Loaded(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
2018-12-11 00:57:40 +08:00
|
|
|
|
Title += " " + BuildInfo.Version + " " + BuildInfo.HeadShaShort;
|
2018-11-07 15:42:30 +08:00
|
|
|
|
|
2019-01-31 14:17:38 +08:00
|
|
|
|
bool skip_ui = false;
|
2018-11-02 00:40:19 +08:00
|
|
|
|
string workdir = string.Empty;
|
2019-01-31 14:17:38 +08:00
|
|
|
|
|
|
|
|
|
CommandLineOption commandLineOption = null;
|
|
|
|
|
Parser.Default
|
|
|
|
|
.ParseArguments<CommandLineOption>(Environment.GetCommandLineArgs())
|
|
|
|
|
.WithParsed(x => commandLineOption = x);
|
|
|
|
|
|
|
|
|
|
if (commandLineOption?.WorkDirectory != null)
|
2018-11-01 23:40:50 +08:00
|
|
|
|
{
|
2019-01-31 14:17:38 +08:00
|
|
|
|
skip_ui = true;
|
|
|
|
|
workdir = commandLineOption.WorkDirectory;
|
2018-11-01 23:40:50 +08:00
|
|
|
|
}
|
2019-01-31 14:17:38 +08:00
|
|
|
|
|
|
|
|
|
if (!skip_ui)
|
2018-11-01 23:40:50 +08:00
|
|
|
|
{
|
2019-01-31 14:17:38 +08:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
workdir = File.ReadAllText(LAST_WORK_DIR_FILE);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception) { }
|
|
|
|
|
var wdw = new WorkDirectoryWindow()
|
|
|
|
|
{
|
|
|
|
|
Owner = this,
|
|
|
|
|
WorkPath = workdir,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (wdw.ShowDialog() == true)
|
|
|
|
|
{
|
|
|
|
|
workdir = wdw.WorkPath;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Environment.Exit(-1);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-11-01 23:40:50 +08:00
|
|
|
|
}
|
2018-03-26 06:28:58 +08:00
|
|
|
|
|
2018-11-01 23:40:50 +08:00
|
|
|
|
if (!Recorder.Initialize(workdir))
|
2018-03-26 06:28:58 +08:00
|
|
|
|
{
|
2019-01-31 14:17:38 +08:00
|
|
|
|
if (!skip_ui)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("初始化错误", "录播姬", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
|
|
|
}
|
2018-11-01 23:40:50 +08:00
|
|
|
|
Environment.Exit(-2);
|
|
|
|
|
return;
|
2018-03-26 06:28:58 +08:00
|
|
|
|
}
|
2018-12-11 00:57:40 +08:00
|
|
|
|
|
|
|
|
|
NotifyIcon.Visibility = Visibility.Visible;
|
2018-03-21 20:56:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-24 09:48:06 +08:00
|
|
|
|
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
|
|
|
|
{
|
2019-04-15 23:27:48 +08:00
|
|
|
|
if (new TimedMessageBox { Title = "关闭录播姬?", Message = "确定要关闭录播姬吗?", CountDown = 10 }.ShowDialog() == true)
|
2018-11-02 00:40:19 +08:00
|
|
|
|
{
|
2019-04-15 23:27:48 +08:00
|
|
|
|
_AddLog = null;
|
|
|
|
|
Recorder.Shutdown();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
File.WriteAllText(LAST_WORK_DIR_FILE, Recorder.Config.WorkDirectory);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception) { }
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
e.Cancel = true;
|
2018-11-02 00:40:19 +08:00
|
|
|
|
}
|
2018-03-24 09:48:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-21 20:56:56 +08:00
|
|
|
|
private void TextBlock_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
|
|
|
|
|
{
|
2018-03-24 02:27:58 +08:00
|
|
|
|
if (sender is TextBlock textBlock)
|
|
|
|
|
{
|
|
|
|
|
Clipboard.SetText(textBlock.Text);
|
|
|
|
|
}
|
2018-03-21 20:56:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-24 02:27:58 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 触发回放剪辑
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
2018-03-21 22:41:34 +08:00
|
|
|
|
private void Clip_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
2018-03-24 02:27:58 +08:00
|
|
|
|
var rr = _GetSenderAsRecordedRoom(sender);
|
2018-10-25 19:20:23 +08:00
|
|
|
|
if (rr == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-21 22:41:34 +08:00
|
|
|
|
Task.Run(() => rr.Clip());
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-24 02:27:58 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 启用自动录制
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
private void EnableAutoRec(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var rr = _GetSenderAsRecordedRoom(sender);
|
2018-10-25 19:20:23 +08:00
|
|
|
|
if (rr == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-24 02:27:58 +08:00
|
|
|
|
Task.Run(() => rr.Start());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 禁用自动录制
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
private void DisableAutoRec(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var rr = _GetSenderAsRecordedRoom(sender);
|
2018-10-25 19:20:23 +08:00
|
|
|
|
if (rr == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-24 02:27:58 +08:00
|
|
|
|
Task.Run(() => rr.Stop());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 手动触发尝试录制
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
private void TriggerRec(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var rr = _GetSenderAsRecordedRoom(sender);
|
2018-10-25 19:20:23 +08:00
|
|
|
|
if (rr == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-24 02:27:58 +08:00
|
|
|
|
Task.Run(() => rr.StartRecord());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 切断当前录制
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
private void CutRec(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var rr = _GetSenderAsRecordedRoom(sender);
|
2018-10-25 19:20:23 +08:00
|
|
|
|
if (rr == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-24 02:27:58 +08:00
|
|
|
|
Task.Run(() => rr.StopRecord());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 删除当前房间
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
private void RemoveRecRoom(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var rr = _GetSenderAsRecordedRoom(sender);
|
2018-10-25 19:20:23 +08:00
|
|
|
|
if (rr == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-24 08:58:46 +08:00
|
|
|
|
Recorder.RemoveRoom(rr);
|
2018-03-24 02:27:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 全部直播间启用自动录制
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
private void EnableAllAutoRec(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
2018-11-28 22:29:35 +08:00
|
|
|
|
Recorder.ToList().ForEach(rr => Task.Run(() => rr.Start()));
|
2018-03-24 02:27:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 全部直播间禁用自动录制
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
private void DisableAllAutoRec(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
2018-11-28 22:29:35 +08:00
|
|
|
|
Recorder.ToList().ForEach(rr => Task.Run(() => rr.Stop()));
|
2018-03-24 02:27:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 添加直播间
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
private void AddRoomidButton_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (int.TryParse(AddRoomidTextBox.Text, out int roomid))
|
|
|
|
|
{
|
|
|
|
|
if (roomid > 0)
|
|
|
|
|
{
|
|
|
|
|
Recorder.AddRoom(roomid);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
logger.Info("房间号是大于0的数字!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
logger.Info("房间号是数字!");
|
|
|
|
|
}
|
|
|
|
|
AddRoomidTextBox.Text = string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SettingsButton_Click(object sender, RoutedEventArgs e)
|
2018-04-14 04:13:53 +08:00
|
|
|
|
{
|
|
|
|
|
ShowSettingsWindow();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ShowSettingsWindow()
|
2018-03-24 02:27:58 +08:00
|
|
|
|
{
|
2018-11-01 23:40:50 +08:00
|
|
|
|
var sw = new SettingsWindow(this, Recorder.Config);
|
2018-03-24 11:07:43 +08:00
|
|
|
|
if (sw.ShowDialog() == true)
|
|
|
|
|
{
|
2018-11-01 23:40:50 +08:00
|
|
|
|
sw.Config.CopyPropertiesTo(Recorder.Config);
|
2018-03-24 11:07:43 +08:00
|
|
|
|
}
|
2018-03-24 02:27:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-24 14:33:05 +08:00
|
|
|
|
private IRecordedRoom _GetSenderAsRecordedRoom(object sender) => (sender as Button)?.DataContext as IRecordedRoom;
|
2018-03-24 09:48:06 +08:00
|
|
|
|
|
2018-12-11 00:57:40 +08:00
|
|
|
|
private void Taskbar_Quit_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Window_StateChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (WindowState == WindowState.Minimized)
|
|
|
|
|
{
|
|
|
|
|
Hide();
|
|
|
|
|
NotifyIcon.ShowBalloonTip("B站录播姬", "录播姬已最小化到托盘,左键单击图标恢复界面。", BalloonIcon.Info);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-03-24 09:48:06 +08:00
|
|
|
|
|
2018-12-11 00:57:40 +08:00
|
|
|
|
private void Taskbar_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Show();
|
|
|
|
|
WindowState = WindowState.Normal;
|
|
|
|
|
Topmost ^= true;
|
|
|
|
|
Topmost ^= true;
|
|
|
|
|
Focus();
|
|
|
|
|
}
|
2018-03-12 18:57:20 +08:00
|
|
|
|
}
|
|
|
|
|
}
|