mirror of
				https://github.com/BubbaGumpShrump/AutoTrackR2.git
				synced 2025-11-04 02:18:59 +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