mirror of
https://github.com/BubbaGumpShrump/AutoTrackR2.git
synced 2025-05-21 00:15:31 +00:00
Streamlink - Almost done.
This commit is contained in:
parent
f7fb63c50f
commit
d7057efe15
6 changed files with 385 additions and 264 deletions
|
@ -19,6 +19,7 @@ namespace AutoTrackR2
|
|||
"AutoTrackR2",
|
||||
"crash.log"
|
||||
);
|
||||
private StreamlinkHandler? _streamlinkHandler;
|
||||
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
|
@ -43,6 +44,7 @@ namespace AutoTrackR2
|
|||
}
|
||||
|
||||
base.OnStartup(e);
|
||||
_streamlinkHandler = new StreamlinkHandler();
|
||||
}
|
||||
|
||||
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
|
|
|
@ -2,14 +2,13 @@
|
|||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Height="410"
|
||||
Width="626">
|
||||
Width="700">
|
||||
|
||||
|
||||
<Grid Background="{DynamicResource BackgroundLightBrush}">
|
||||
<!-- Main Layout Grid -->
|
||||
<Grid Margin="0,0,5,7">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<!-- One row for the content, the other for buttons -->
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
@ -22,9 +21,9 @@
|
|||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Section for Config Fields -->
|
||||
<StackPanel Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Height="389">
|
||||
<StackPanel Grid.Row="0"
|
||||
VerticalAlignment="Top"
|
||||
Margin="20,10,20,0">
|
||||
<!-- Log File -->
|
||||
<StackPanel Margin="0,5,0,10"
|
||||
Orientation="Horizontal">
|
||||
|
@ -38,11 +37,11 @@
|
|||
FontSize="16"
|
||||
Margin="0,5,0,5"
|
||||
FontFamily="{StaticResource Roboto}"/>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Margin="30,0,0,0">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox Name="LogFilePath"
|
||||
Width="330"
|
||||
Width="260"
|
||||
Height="30"
|
||||
Margin="10,0,0,0"
|
||||
Style="{StaticResource RoundedTextBox}"/>
|
||||
<Button Content="Browse"
|
||||
Width="75"
|
||||
|
@ -51,6 +50,13 @@
|
|||
Margin="5,0"
|
||||
Style="{StaticResource ButtonStyle}"
|
||||
Click="LogFileBrowseButton_Click"/>
|
||||
<Button Content="Open"
|
||||
Width="75"
|
||||
Height="30"
|
||||
FontFamily="{StaticResource Orbitron}"
|
||||
Margin="5,0"
|
||||
Style="{StaticResource ButtonStyle}"
|
||||
Click="LogFileOpenButton_Click"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
|
@ -66,11 +72,11 @@
|
|||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,5,0,5"/>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Margin="30,0,0,0">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox Name="ApiUrl"
|
||||
Width="330"
|
||||
Width="260"
|
||||
Height="30"
|
||||
Margin="10,0,0,0"
|
||||
Style="{StaticResource RoundedTextBox}"/>
|
||||
<Button Content="Test"
|
||||
Width="75"
|
||||
|
@ -95,9 +101,9 @@
|
|||
FontSize="16"
|
||||
Margin="0,5,0,5"/>
|
||||
<PasswordBox Name="ApiKey"
|
||||
Width="330"
|
||||
Width="260"
|
||||
Height="30"
|
||||
Margin="33,0,0,0"
|
||||
Margin="10,0,0,0"
|
||||
Style="{StaticResource RoundedPasswordBox}"/>
|
||||
</StackPanel>
|
||||
|
||||
|
@ -115,7 +121,7 @@
|
|||
Margin="0,5,0,5"/>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox Name="VideoPath"
|
||||
Width="330"
|
||||
Width="260"
|
||||
Height="30"
|
||||
Margin="10,0,0,0"
|
||||
Style="{StaticResource RoundedTextBox}"/>
|
||||
|
@ -126,201 +132,214 @@
|
|||
Margin="5,0"
|
||||
Style="{StaticResource ButtonStyle}"
|
||||
Click="VideoPathBrowseButton_Click"/>
|
||||
<Button Content="Open"
|
||||
Width="75"
|
||||
Height="30"
|
||||
FontFamily="{StaticResource Orbitron}"
|
||||
Margin="5,0"
|
||||
Style="{StaticResource ButtonStyle}"
|
||||
Click="VideoPathOpenButton_Click"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Toggle Settings Grid -->
|
||||
<Grid Margin="0,0,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Left Column Controls -->
|
||||
|
||||
<!-- Visor Wipe Toggle -->
|
||||
<StackPanel Grid.Column="0" Grid.Row="0"
|
||||
Orientation="Horizontal"
|
||||
Margin="0,0,5,5">
|
||||
<TextBlock Text="ⓘ"
|
||||
ToolTip="Perform a Visor Wipe animation on player kill. Requires AHKv2."
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="20"
|
||||
Margin="0,4,3,0"/>
|
||||
<TextBlock Text="Visor Wipe:"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,7,0,0"/>
|
||||
<Slider Name="VisorWipeSlider"
|
||||
Minimum="0"
|
||||
Maximum="1"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
Value="0"
|
||||
Style="{StaticResource ToggleSliderStyle}"
|
||||
Margin="10,-4,0,0"
|
||||
Width="100"
|
||||
ValueChanged="VisorWipeSlider_ValueChanged"/>
|
||||
</StackPanel>
|
||||
<!-- Left Column Controls -->
|
||||
|
||||
<!-- Video Record Toggle -->
|
||||
<StackPanel Grid.Column="0" Grid.Row="1"
|
||||
Orientation="Horizontal"
|
||||
Margin="0,0,5,5">
|
||||
<TextBlock Text="ⓘ"
|
||||
ToolTip="Record video on player kill. Requires AHKv2."
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="20"
|
||||
Margin="0,4,3,0"/>
|
||||
<TextBlock Text="Video Record:"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,7,0,0"/>
|
||||
<Slider Name="VideoRecordSlider"
|
||||
Minimum="0"
|
||||
Maximum="1"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
Value="0"
|
||||
Style="{StaticResource ToggleSliderStyle}"
|
||||
Margin="10,-4,0,0"
|
||||
Width="100"
|
||||
ValueChanged="VideoRecordSlider_ValueChanged"/>
|
||||
</StackPanel>
|
||||
<!-- Visor Wipe Toggle -->
|
||||
<StackPanel Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
Orientation="Horizontal"
|
||||
Margin="0,0,5,5">
|
||||
<TextBlock Text="ⓘ"
|
||||
ToolTip="Perform a Visor Wipe animation on player kill. Requires AHKv2."
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="20"
|
||||
Margin="0,4,3,0"/>
|
||||
<TextBlock Text="Visor Wipe:"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,7,0,0"/>
|
||||
<Slider Name="VisorWipeSlider"
|
||||
Minimum="0"
|
||||
Maximum="1"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
Value="0"
|
||||
Style="{StaticResource ToggleSliderStyle}"
|
||||
Margin="10,-4,0,0"
|
||||
Width="100"
|
||||
ValueChanged="VisorWipeSlider_ValueChanged"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Offline Mode Toggle -->
|
||||
<StackPanel Grid.Column="0" Grid.Row="2"
|
||||
Orientation="Horizontal"
|
||||
Margin="0,0,5,5">
|
||||
<TextBlock Text="ⓘ"
|
||||
ToolTip="With Offline Mode enabled, kills will not be submitted to the configured API."
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="20"
|
||||
Margin="0,4,3,0"/>
|
||||
<TextBlock Text="Offline Mode:"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,7,0,0"/>
|
||||
<Slider Name="OfflineModeSlider"
|
||||
Minimum="0"
|
||||
Maximum="1"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
Value="0"
|
||||
Style="{StaticResource ToggleSliderStyle}"
|
||||
Margin="10,-4,0,0"
|
||||
Width="100"
|
||||
ValueChanged="OfflineModeSlider_ValueChanged"/>
|
||||
</StackPanel>
|
||||
<!-- Video Record Toggle -->
|
||||
<StackPanel Grid.Column="0"
|
||||
Grid.Row="1"
|
||||
Orientation="Horizontal"
|
||||
Margin="0,0,5,5">
|
||||
<TextBlock Text="ⓘ"
|
||||
ToolTip="Record video on player kill. Requires AHKv2."
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="20"
|
||||
Margin="0,4,3,0"/>
|
||||
<TextBlock Text="Video Record:"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,7,0,0"/>
|
||||
<Slider Name="VideoRecordSlider"
|
||||
Minimum="0"
|
||||
Maximum="1"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
Value="0"
|
||||
Style="{StaticResource ToggleSliderStyle}"
|
||||
Margin="10,-4,0,0"
|
||||
Width="100"
|
||||
ValueChanged="VideoRecordSlider_ValueChanged"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Right Column Controls -->
|
||||
|
||||
<!-- Streamlink Toggle -->
|
||||
<StackPanel Grid.Column="1" Grid.Row="0"
|
||||
Orientation="Horizontal"
|
||||
Margin="5,0,0,5">
|
||||
<TextBlock Text="ⓘ"
|
||||
ToolTip="Use Streamlink for video recording."
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="20"
|
||||
Margin="0,4,3,0"/>
|
||||
<TextBlock Text="Streamlink:"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,7,0,0"/>
|
||||
<Slider Name="StreamlinkSlider"
|
||||
Minimum="0"
|
||||
Maximum="1"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
Value="0"
|
||||
Style="{StaticResource ToggleSliderStyle}"
|
||||
Margin="10,-4,0,0"
|
||||
Width="100"
|
||||
ValueChanged="StreamlinkSlider_ValueChanged"/>
|
||||
</StackPanel>
|
||||
<!-- Offline Mode Toggle -->
|
||||
<StackPanel Grid.Column="0"
|
||||
Grid.Row="2"
|
||||
Orientation="Horizontal"
|
||||
Margin="0,0,5,5">
|
||||
<TextBlock Text="ⓘ"
|
||||
ToolTip="With Offline Mode enabled, kills will not be submitted to the configured API."
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="20"
|
||||
Margin="0,4,3,0"/>
|
||||
<TextBlock Text="Offline Mode:"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,7,0,0"/>
|
||||
<Slider Name="OfflineModeSlider"
|
||||
Minimum="0"
|
||||
Maximum="1"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
Value="0"
|
||||
Style="{StaticResource ToggleSliderStyle}"
|
||||
Margin="10,-4,0,0"
|
||||
Width="100"
|
||||
ValueChanged="OfflineModeSlider_ValueChanged"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Streamlink Duration -->
|
||||
<StackPanel Grid.Column="1" Grid.Row="1"
|
||||
Orientation="Horizontal"
|
||||
Margin="5,0,0,5">
|
||||
<TextBlock Text="ⓘ"
|
||||
ToolTip="Duration of Streamlink recordings in seconds."
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="20"
|
||||
Margin="0,4,3,0"/>
|
||||
<TextBlock Text="Duration:"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,7,0,0"/>
|
||||
<Slider Name="StreamlinkDurationSlider"
|
||||
Minimum="10"
|
||||
Maximum="300"
|
||||
TickFrequency="10"
|
||||
IsSnapToTickEnabled="True"
|
||||
Value="30"
|
||||
Style="{StaticResource SliderStyle}"
|
||||
Margin="10,-4,0,0"
|
||||
Width="100"
|
||||
ValueChanged="StreamlinkDurationSlider_ValueChanged"/>
|
||||
<TextBlock Name="StreamlinkDurationText"
|
||||
Text="30s"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="5,7,0,0"/>
|
||||
</StackPanel>
|
||||
<!-- Right Column Controls -->
|
||||
|
||||
<!-- Test Streamlink Button -->
|
||||
<Button Grid.Column="1" Grid.Row="2"
|
||||
Content="Test Streamlink"
|
||||
Width="120"
|
||||
Height="30"
|
||||
FontFamily="{StaticResource Orbitron}"
|
||||
Margin="5,0,0,5"
|
||||
Style="{StaticResource ButtonStyle}"
|
||||
Click="TestStreamlinkButton_Click"/>
|
||||
<!-- Streamlink Toggle -->
|
||||
<StackPanel Grid.Column="1"
|
||||
Grid.Row="0"
|
||||
Orientation="Horizontal"
|
||||
Margin="5,0,0,5">
|
||||
<TextBlock Text="ⓘ"
|
||||
ToolTip="Use Streamlink for video recording."
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="20"
|
||||
Margin="0,4,3,0"/>
|
||||
<TextBlock Text="Streamlink:"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,7,0,0"/>
|
||||
<Slider Name="StreamlinkSlider"
|
||||
Minimum="0"
|
||||
Maximum="1"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
Value="0"
|
||||
Style="{StaticResource ToggleSliderStyle}"
|
||||
Margin="10,-4,0,0"
|
||||
Width="100"
|
||||
ValueChanged="StreamlinkSlider_ValueChanged"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Theme Slider -->
|
||||
<StackPanel Grid.Column="0" Grid.Row="4"
|
||||
Grid.ColumnSpan="2"
|
||||
Orientation="Horizontal"
|
||||
Margin="0,10,0,5">
|
||||
<TextBlock Text="Theme:"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,7,10,0"/>
|
||||
<Slider x:Name="ThemeSlider"
|
||||
Minimum="0"
|
||||
Value="0"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
ValueChanged="ThemeSlider_ValueChanged"
|
||||
Width="447"
|
||||
Style="{StaticResource ThreePositionSlider}"/>
|
||||
</StackPanel>
|
||||
<!-- Streamlink Duration -->
|
||||
<StackPanel Grid.Column="1"
|
||||
Grid.Row="1"
|
||||
Orientation="Horizontal"
|
||||
Margin="5,0,0,5">
|
||||
<TextBlock Text="ⓘ"
|
||||
ToolTip="Duration of Streamlink recordings in seconds."
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="20"
|
||||
Margin="0,4,3,0"/>
|
||||
<TextBlock Text="Duration:"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,7,0,0"/>
|
||||
<Slider Name="StreamlinkDurationSlider"
|
||||
Minimum="10"
|
||||
Maximum="600"
|
||||
TickFrequency="30"
|
||||
IsSnapToTickEnabled="True"
|
||||
Value="30"
|
||||
Style="{StaticResource SliderStyle}"
|
||||
Margin="10,-4,0,0"
|
||||
Width="100"
|
||||
ValueChanged="StreamlinkDurationSlider_ValueChanged"/>
|
||||
<TextBlock Name="StreamlinkDurationText"
|
||||
Text="30s"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="5,7,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Test Streamlink Button -->
|
||||
<Button Grid.Column="1"
|
||||
Grid.Row="2"
|
||||
Content="Test Streamlink"
|
||||
Width="120"
|
||||
Height="30"
|
||||
FontFamily="{StaticResource Orbitron}"
|
||||
Margin="5,0,0,5"
|
||||
Style="{StaticResource ButtonStyle}"
|
||||
Click="TestStreamlinkButton_Click"/>
|
||||
|
||||
<!-- Theme Slider -->
|
||||
<StackPanel Grid.Column="0"
|
||||
Grid.Row="3"
|
||||
Grid.ColumnSpan="2"
|
||||
Orientation="Horizontal"
|
||||
Margin="0,0,0,5">
|
||||
<TextBlock Text="Theme:"
|
||||
Foreground="{DynamicResource TextBrush}"
|
||||
FontSize="16"
|
||||
Margin="0,7,10,0"/>
|
||||
<Slider x:Name="ThemeSlider"
|
||||
Minimum="0"
|
||||
Value="0"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
ValueChanged="ThemeSlider_ValueChanged"
|
||||
Width="350"
|
||||
Style="{StaticResource ThreePositionSlider}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Save Button -->
|
||||
<StackPanel Grid.Column="2"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Margin="0,0,0,10">
|
||||
<Button x:Name="SaveButton"
|
||||
Content="Save"
|
||||
Width="100"
|
||||
Height="40"
|
||||
Style="{StaticResource ButtonStyle}"
|
||||
FontFamily="{StaticResource Orbitron}"
|
||||
Click="SaveButton_Click"/>
|
||||
</StackPanel>
|
||||
<Button x:Name="SaveButton"
|
||||
Grid.Row="1"
|
||||
Content="Save"
|
||||
Width="100"
|
||||
Height="40"
|
||||
Style="{StaticResource ButtonStyle}"
|
||||
FontFamily="{StaticResource Orbitron}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Margin="0,0,80,20"
|
||||
Click="SaveButton_Click"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -37,9 +37,18 @@ public partial class ConfigPage : UserControl
|
|||
VideoRecordSlider.Value = ConfigManager.VideoRecord;
|
||||
OfflineModeSlider.Value = ConfigManager.OfflineMode;
|
||||
ThemeSlider.Value = ConfigManager.Theme;
|
||||
StreamlinkSlider.Value = ConfigManager.StreamlinkEnabled;
|
||||
StreamlinkDurationSlider.Value = ConfigManager.StreamlinkDuration;
|
||||
|
||||
// Initialize Streamlink slider style
|
||||
StreamlinkSlider.Style = (Style)Application.Current.FindResource("FalseToggleStyle");
|
||||
if (StreamlinkSlider.Value == 0)
|
||||
{
|
||||
StreamlinkSlider.Style = (Style)Application.Current.FindResource("FalseToggleStyle");
|
||||
}
|
||||
else
|
||||
{
|
||||
StreamlinkSlider.Style = (Style)Application.Current.FindResource("ToggleSliderStyle");
|
||||
}
|
||||
|
||||
ApplyToggleModeStyle(OfflineModeSlider.Value, VisorWipeSlider.Value, VideoRecordSlider.Value);
|
||||
|
||||
|
@ -430,6 +439,19 @@ public partial class ConfigPage : UserControl
|
|||
private void StreamlinkSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
|
||||
{
|
||||
Slider slider = (Slider)sender;
|
||||
|
||||
// Only allow enabling if streamlink is installed
|
||||
if (slider.Value == 1)
|
||||
{
|
||||
if (!StreamlinkHandler.IsStreamlinkInstalled())
|
||||
{
|
||||
MessageBox.Show("Streamlink is not installed. Please install Streamlink to use this feature.",
|
||||
"Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
slider.Value = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ConfigManager.StreamlinkEnabled = (int)slider.Value;
|
||||
|
||||
// Apply the appropriate style based on the value
|
||||
|
@ -459,82 +481,46 @@ public partial class ConfigPage : UserControl
|
|||
{
|
||||
// Get the duration from the slider
|
||||
int duration = (int)StreamlinkDurationSlider.Value;
|
||||
|
||||
// Check if streamlink is installed
|
||||
var versionInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "streamlink",
|
||||
Arguments = "--version",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using (var process = Process.Start(versionInfo))
|
||||
{
|
||||
if (process == null)
|
||||
{
|
||||
MessageBox.Show("Streamlink is not installed. Please install Streamlink to use this feature.",
|
||||
"Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
// Calculate the total duration (30 seconds before + configured duration)
|
||||
int totalDuration = 30 + duration;
|
||||
|
||||
string output = process.StandardOutput.ReadToEnd();
|
||||
process.WaitForExit();
|
||||
|
||||
if (process.ExitCode != 0)
|
||||
{
|
||||
MessageBox.Show("Streamlink is not installed or not working correctly. Please install Streamlink to use this feature.",
|
||||
"Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Test recording functionality
|
||||
var testUrl = "https://www.twitch.tv/starcitizen"; // Example URL for testing
|
||||
var outputPath = Path.Combine(
|
||||
ConfigManager.VideoPath ?? Environment.GetFolderPath(Environment.SpecialFolder.MyVideos),
|
||||
"streamlink_test.mp4"
|
||||
);
|
||||
|
||||
var recordInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "streamlink",
|
||||
Arguments = $"{testUrl} best -o {outputPath}",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using (var process = Process.Start(recordInfo))
|
||||
{
|
||||
if (process == null)
|
||||
{
|
||||
MessageBox.Show("Failed to start test recording.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for a short duration (5 seconds) to test recording
|
||||
await Task.Delay(5000);
|
||||
|
||||
try
|
||||
{
|
||||
if (!process.HasExited)
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
MessageBox.Show($"Streamlink test recording completed successfully.\nA 5-second test recording was saved to:\n{outputPath}",
|
||||
"Success", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
// Test recording functionality, we're using spacecutlet cause need a good tester.
|
||||
TrackREventDispatcher.OnStreamlinkRecordEvent("spacecutlet");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"Error testing Streamlink: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void LogFileOpenButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(LogFilePath.Text))
|
||||
{
|
||||
string directory = Path.GetDirectoryName(LogFilePath.Text) ?? string.Empty;
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Process.Start("explorer.exe", directory);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Directory does not exist.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void VideoPathOpenButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(VideoPath.Text) && Directory.Exists(VideoPath.Text))
|
||||
{
|
||||
Process.Start("explorer.exe", VideoPath.Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Directory does not exist.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Theme
|
||||
|
|
88
AutoTrackR2/StreamlinkHandler.cs
Normal file
88
AutoTrackR2/StreamlinkHandler.cs
Normal file
|
@ -0,0 +1,88 @@
|
|||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace AutoTrackR2;
|
||||
|
||||
public class StreamlinkHandler
|
||||
{
|
||||
public StreamlinkHandler()
|
||||
{
|
||||
TrackREventDispatcher.StreamlinkRecordEvent += HandleStreamlinkRecord;
|
||||
}
|
||||
|
||||
public static bool IsStreamlinkInstalled()
|
||||
{
|
||||
try
|
||||
{
|
||||
var checkInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "where",
|
||||
Arguments = "streamlink",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using (var process = Process.Start(checkInfo))
|
||||
{
|
||||
if (process == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string output = process.StandardOutput.ReadToEnd();
|
||||
process.WaitForExit();
|
||||
|
||||
return process.ExitCode == 0 && !string.IsNullOrEmpty(output);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private async void HandleStreamlinkRecord(string streamerHandle)
|
||||
{
|
||||
if (ConfigManager.StreamlinkEnabled != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var outputPath = Path.Combine(
|
||||
ConfigManager.VideoPath ?? Environment.GetFolderPath(Environment.SpecialFolder.MyVideos),
|
||||
$"kill_{DateTime.Now:yyyyMMdd_HHmmss}.mp4"
|
||||
);
|
||||
|
||||
// Calculate the duration for recording (30 seconds before + configured duration after)
|
||||
var totalDuration = 30 + ConfigManager.StreamlinkDuration;
|
||||
|
||||
var recordInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "streamlink",
|
||||
Arguments = $"https://www.twitch.tv/{streamerHandle} best --hls-live-edge 30 --hls-duration {totalDuration} -o {outputPath}",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using (var process = Process.Start(recordInfo))
|
||||
{
|
||||
if (process == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for the recording to complete
|
||||
await process.WaitForExitAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log the error but don't crash the application
|
||||
Debug.WriteLine($"Error recording streamlink clip: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -54,4 +54,11 @@ public static class TrackREventDispatcher
|
|||
{
|
||||
JumpDriveStateChangedEvent?.Invoke(data);
|
||||
}
|
||||
|
||||
public static event Action<string>? StreamlinkRecordEvent;
|
||||
|
||||
public static void OnStreamlinkRecordEvent(string streamerHandle)
|
||||
{
|
||||
StreamlinkRecordEvent?.Invoke(streamerHandle);
|
||||
}
|
||||
}
|
|
@ -172,7 +172,26 @@ public static class WebHandler
|
|||
else if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
Console.WriteLine("Successfully submitted kill data");
|
||||
Console.WriteLine($"Response: {await response.Content.ReadAsStringAsync()}");
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
Console.WriteLine($"Response: {responseContent}");
|
||||
|
||||
// Check if the response contains a streamer field
|
||||
try
|
||||
{
|
||||
var responseData = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(responseContent);
|
||||
if (responseData != null && responseData.TryGetValue("streamer", out JsonElement streamerElement))
|
||||
{
|
||||
string streamerHandle = streamerElement.GetString() ?? string.Empty;
|
||||
if (!string.IsNullOrEmpty(streamerHandle))
|
||||
{
|
||||
TrackREventDispatcher.OnStreamlinkRecordEvent(streamerHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error parsing streamer from response: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue