Skip to content

Commit

Permalink
Merge pull request #17 from sajmons/ssh.net
Browse files Browse the repository at this point in the history
Added UVC and Raspberry Pi camera support
  • Loading branch information
sajmons authored Feb 5, 2024
2 parents 347a8bb + fa6e906 commit b413b6e
Show file tree
Hide file tree
Showing 16 changed files with 234 additions and 130 deletions.
4 changes: 3 additions & 1 deletion CollimationCircles/App.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@
<PathGeometry x:Key="IconData.LogFile">M486.201,196.124h-13.166V132.59c0-0.396-0.062-0.795-0.115-1.196c-0.021-2.523-0.825-5-2.552-6.963L364.657,3.677 c-0.033-0.031-0.064-0.042-0.085-0.073c-0.63-0.707-1.364-1.292-2.143-1.795c-0.229-0.157-0.461-0.286-0.702-0.421 c-0.672-0.366-1.387-0.671-2.121-0.892c-0.2-0.055-0.379-0.136-0.577-0.188C358.23,0.118,357.401,0,356.562,0H96.757 C84.894,0,75.256,9.651,75.256,21.502v174.613H62.092c-16.971,0-30.732,13.756-30.732,30.733v159.812 c0,16.968,13.761,30.731,30.732,30.731h13.164V526.79c0,11.854,9.638,21.501,21.501,21.501h354.776 c11.853,0,21.501-9.647,21.501-21.501V417.392h13.166c16.966,0,30.729-13.764,30.729-30.731V226.854 C516.93,209.872,503.167,196.124,486.201,196.124z M96.757,21.502h249.054v110.009c0,5.939,4.817,10.75,10.751,10.75h94.972v53.861 H96.757V21.502z M317.816,303.427c0,47.77-28.973,76.746-71.558,76.746c-43.234,0-68.531-32.641-68.531-74.152 c0-43.679,27.887-76.319,70.906-76.319C293.389,229.702,317.816,263.213,317.816,303.427z M82.153,377.79V232.085h33.073v118.039 h57.944v27.66H82.153V377.79z M451.534,520.962H96.757v-103.57h354.776V520.962z M461.176,371.092 c-10.162,3.454-29.402,8.209-48.641,8.209c-26.589,0-45.833-6.698-59.24-19.664c-13.396-12.535-20.75-31.568-20.529-52.967 c0.214-48.436,35.448-76.108,83.229-76.108c18.814,0,33.292,3.688,40.431,7.139l-6.92,26.37 c-7.999-3.457-17.942-6.268-33.942-6.268c-27.449,0-48.209,15.567-48.209,47.134c0,30.049,18.807,47.771,45.831,47.771 c7.564,0,13.623-0.852,16.21-2.152v-30.488h-22.478v-25.723h54.258V371.092L461.176,371.092z M212.533,305.37c0,28.535,13.407,48.64,35.452,48.64c22.268,0,35.021-21.186,35.021-49.5 c0-26.153-12.539-48.655-35.237-48.655C225.504,255.854,212.533,277.047,212.533,305.37z</PathGeometry>
<PathGeometry x:Key="IconData.Visible">M24 9c-10 0-18.54 6.22-22 15 3.46 8.78 12 15 22 15 10.01 0 18.54-6.22 22-15-3.46-8.78-11.99-15-22-15zm0 25c-5.52 0-10-4.48-10-10s4.48-10 10-10 10 4.48 10 10-4.48 10-10 10zm0-16c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6z</PathGeometry>
<PathGeometry x:Key="IconData.Hidden">M24 14c5.52 0 10 4.48 10 10 0 1.29-.26 2.52-.71 3.65l5.85 5.85c3.02-2.52 5.4-5.78 6.87-9.5-3.47-8.78-12-15-22.01-15-2.8 0-5.48.5-7.97 1.4l4.32 4.31c1.13-.44 2.36-.71 3.65-.71zm-20-5.45l4.56 4.56.91.91c-3.3 2.58-5.91 6.01-7.47 9.98 3.46 8.78 12 15 22 15 3.1 0 6.06-.6 8.77-1.69l.85.85 5.83 5.84 2.55-2.54-35.45-35.46-2.55 2.55zm11.06 11.05l3.09 3.09c-.09.43-.15.86-.15 1.31 0 3.31 2.69 6 6 6 .45 0 .88-.06 1.3-.15l3.09 3.09c-1.33.66-2.81 1.06-4.39 1.06-5.52 0-10-4.48-10-10 0-1.58.4-3.06 1.06-4.4zm8.61-1.57l6.3 6.3.03-.33c0-3.31-2.69-6-6-6l-.33.03z</PathGeometry>
<PathGeometry x:Key="IconData.Info">M11 10.9794C11 10.4271 11.4477 9.97937 12 9.97937C12.5523 9.97937 13 10.4271 13 10.9794V16.9794C13 17.5317 12.5523 17.9794 12 17.9794C11.4477 17.9794 11 17.5317 11 16.9794V10.9794Z M12 6.05115C11.4477 6.05115 11 6.49886 11 7.05115C11 7.60343 11.4477 8.05115 12 8.05115C12.5523 8.05115 13 7.60343 13 7.05115C13 6.49886 12.5523 6.05115 12 6.05115Z M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2ZM4 12C4 16.4183 7.58172 20 12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12Z</PathGeometry>
<PathGeometry x:Key="IconData.Info">M11 10.9794C11 10.4271 11.4477 9.97937 12 9.97937C12.5523 9.97937 13 10.4271 13 10.9794V16.9794C13 17.5317 12.5523 17.9794 12 17.9794C11.4477 17.9794 11 17.5317 11 16.9794V10.9794Z M12 6.05115C11.4477 6.05115 11 6.49886 11 7.05115C11 7.60343 11.4477 8.05115 12 8.05115C12.5523 8.05115 13 7.60343 13 7.05115C13 6.49886 12.5523 6.05115 12 6.05115Z M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2ZM4 12C4 16.4183 7.58172 20 12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12Z</PathGeometry>
<PathGeometry x:Key="IconData.Play">M405.2,232.9L126.8,67.2c-3.4-2-6.9-3.2-10.9-3.2c-10.9,0-19.8,9-19.8,20H96v344h0.1c0,11,8.9,20,19.8,20 c4.1,0,7.5-1.4,11.2-3.4l278.1-165.5c6.6-5.5,10.8-13.8,10.8-23.1C416,246.7,411.8,238.5,405.2,232.9z</PathGeometry>
<PathGeometry x:Key="IconData.Stop">M437.4,64H74.6C68.7,64,64,68.7,64,74.6v362.8c0,5.9,4.7,10.6,10.6,10.6h362.8c5.8,0,10.6-4.7,10.6-10.6V74.6 C448,68.7,443.2,64,437.4,64z</PathGeometry>

<!-- Helper Icons -->
<PathGeometry x:Key="IconData.Circle">M256 0c-141.385 0-256 114.615-256 256s114.615 256 256 256 256-114.615 256-256-114.615-256-256-256zM256 448c-106.039 0-192-85.961-192-192s85.961-192 192-192c106.039 0 192 85.961 192 192s-85.961 192-192 192z</PathGeometry>
Expand Down
2 changes: 1 addition & 1 deletion CollimationCircles/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ private static void ConfigureServices()
.AddSingleton<SettingsViewModel>()
.AddSingleton<StreamViewModel>()
.AddSingleton<AppLogViewModel>()
.AddTransient<AboutViewModel>()
.AddTransient<AboutViewModel>()
.AddTransient<IDrawHelperService, DrawHelperService>()
.AddSingleton<IKeyHandlingService, KeyHandlingService>()
.BuildServiceProvider());
Expand Down
4 changes: 2 additions & 2 deletions CollimationCircles/CollimationCircles.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<PackageProjectUrl>https://github.com/sajmons/CollimationCircles</PackageProjectUrl>
<RepositoryUrl>https://github.com/sajmons/CollimationCircles</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Version>3.0.0</Version>
<Version>3.1.0</Version>
<Authors>Simon Šander</Authors>
<Product>Collimation Circles</Product>
<Copyright>Copyright © 2023</Copyright>
Expand Down Expand Up @@ -44,7 +44,7 @@
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.2.8" />
<PackageReference Include="Octokit" Version="9.1.0" />
<PackageReference Include="Octokit" Version="9.1.1" />

<PackageReference Condition="$(RuntimeIdentifier.StartsWith('win')) And '$(Configuration)' == 'Release'" Include="VideoLAN.LibVLC.Windows" Version="3.0.20" />
<PackageReference Condition="$(RuntimeIdentifier.StartsWith('osx')) And '$(Configuration)' == 'Release'" Include="VideoLAN.LibVLC.Mac" Version="3.1.3.1" />
Expand Down
2 changes: 1 addition & 1 deletion CollimationCircles/Controls/SettingsUserControl.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
Header="{DynamicResource Text.WebCamStream}"
IsExpanded="{Binding CameraVideoStreamExpanded}">
<controls:StreamUserControl/>
</Expander>
</Expander>
</StackPanel>
</ScrollViewer>
</TabItem>
Expand Down
100 changes: 64 additions & 36 deletions CollimationCircles/Controls/StreamUserControl.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,44 +13,72 @@

<TextBox
Text="{Binding FullAddress, Mode=TwoWay}"
IsEnabled="{Binding !#autoStartCamStream.IsChecked}"
VerticalAlignment="Center"/>
<Grid ColumnDefinitions="*,30">
VerticalAlignment="Center"
FocusAdorner=""/>
<StackPanel
Orientation="Horizontal"
Spacing="10">
<ToggleButton
IsChecked="{Binding IsPlaying}"
Command="{Binding PlayPauseCommand}"
ToolTip.Tip="{DynamicResource Text.PlayStopCameraVideoStream}">
<Panel>
<PathIcon
Foreground="{DynamicResource Color2}"
Classes="visibility-on"
Data="{StaticResource IconData.Stop}" />
<PathIcon
Foreground="{DynamicResource Color2}"
Classes="visibility-off"
Data="{StaticResource IconData.Play}" />
</Panel>
<ToggleButton.Styles>
<Style Selector="ToggleButton PathIcon.visibility-on">
<Setter Property="IsVisible" Value="False"/>
</Style>
<Style Selector="ToggleButton:checked PathIcon.visibility-on">
<Setter Property="IsVisible" Value="True"/>
</Style>
<Style Selector="ToggleButton PathIcon.visibility-off">
<Setter Property="IsVisible" Value="True"/>
</Style>
<Style Selector="ToggleButton:checked PathIcon.visibility-off">
<Setter Property="IsVisible" Value="False"/>
</Style>
</ToggleButton.Styles>
</ToggleButton>
<Button
HorizontalContentAlignment="Center"
HorizontalAlignment="Stretch"
Content="{Binding ButtonTitle}"
Command="{Binding PlayPauseCommand}"/>
<PathIcon
Grid.Column="1"
ToolTip.Tip="{DynamicResource Text.LibcameraVidCommand}"
Foreground="{DynamicResource Color2}"
Data="{StaticResource IconData.Help}" />
</Grid>
<Grid ColumnDefinitions="*,30">
<CheckBox
Name="autoStartCamStream"
Content="{DynamicResource Text.AutoStartCameraStream}"
IsEnabled="{Binding AreControlsEnabled}"
IsChecked="{Binding LocalConnectionPossible}" />
<PathIcon
Grid.Column="1"
ToolTip.Tip="{DynamicResource Text.AutoStartCameraStreamHelp}"
Foreground="{DynamicResource Color2}"
Data="{StaticResource IconData.Help}" />
</Grid>
Command="{Binding ResetAddressCommand}"
ToolTip.Tip="{DynamicResource Text.ResetCameraStreamAddress}"
Grid.Column="2"
IsEnabled="{Binding !IsPlaying}">
<PathIcon
Foreground="{DynamicResource Color2}"
Data="{StaticResource IconData.Reset}" />
</Button>
</StackPanel>
<StackPanel
Orientation="Vertical"
IsEnabled="{Binding AreControlsEnabled}">
<TextBlock
VerticalAlignment="Bottom"
TextWrapping="WrapWithOverflow"
Text="{DynamicResource Text.CameraStreamTimeout}" />
<NumericUpDown
Increment="100"
Value="{Binding CameraStreamTimeout}"
Minimum="{Binding CameraStreamTimeoutMin}"
Maximum="{Binding CameraStreamTimeoutMax}"/>
Orientation="Vertical"
IsEnabled="{Binding !IsPlaying}">
<TextBlock Text="{DynamicResource Text.CameraType}"/>
<WrapPanel
Orientation="Horizontal">
<RadioButton
Margin="0 0 10 0"
GroupName="CameraType"
Content="UVC"
IsChecked="{Binding IsUVC}"/>
<RadioButton
Margin="0 0 10 0"
GroupName="CameraType"
Content="Raspberry PI"
IsChecked="{Binding IsRaspberryPi}"
IsEnabled="{Binding !IsWindows}"/>
<RadioButton
GroupName="CameraType"
Content="{DynamicResource Text.RemoteCameraType}"
IsChecked="{Binding IsRemote}"/>
</WrapPanel>
</StackPanel>
<CheckBox
Content="{DynamicResource Text.CameraStreamSeparateWindow}"
Expand Down
2 changes: 1 addition & 1 deletion CollimationCircles/Helper/Constraints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ internal class Constraints
internal const int LabelSizeMin = 5;
internal const int LabelSizeMax = 1000;

internal const string MurlRegEx = "^(?:(?<protocol>tcp\\/h264|http|https):\\/\\/)?(?<host>[\\w\\.-]+)(?::(?<port>\\d+))?(?<path>\\/\\S*)?$";
internal const string MurlRegEx = "^(?:(?<protocol>tcp\\/h264|http|https|dshow|v4l2|qtcapture):\\/\\/)?(?<host>[\\w\\.-]+)?(?::(?<port>\\d+))?(?<path>\\/\\S*)?$";
}
}
6 changes: 3 additions & 3 deletions CollimationCircles/NLog.config
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
</targets>

<rules>
<logger name="*" minlevel="Error" writeTo="logconsole" />
<logger name="*" minlevel="Error" writeTo="file" />
<logger name="*" minlevel="Info" writeTo="memory" />
<logger name="*" minlevel="Debug" writeTo="logconsole" />
<logger name="*" minlevel="Debug" writeTo="file" />
<logger name="*" minlevel="Debug" writeTo="memory" />
</rules>
</nlog>
5 changes: 4 additions & 1 deletion CollimationCircles/Resources/Lang/de-DE.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,10 @@
<system:String x:Key="Text.PayPalDonation">Mit dieser Spende unterstützen Sie mich bei der Weiterentwicklung der Collimation Circles-Anwendung. Danke schön!</system:String>
<system:String x:Key="Text.PayPalDonate">PayPal Donate</system:String>
<system:String x:Key="Text.CameraStreamTimeout">Zeitüberschreitung beim Warten auf den Videostream</system:String>
<system:String x:Key="Text.LibcameraVidCommand">Führen Sie den folgenden Befehl im Linux-Terminal aus, bevor Sie auf die Schaltfläche Start klicken: libcamera-vid -t 0 --inline --nopreview --listen -o tcp://0.0.0.0:8080</system:String>
<system:String x:Key="Text.ResetCameraStreamAddress">Setzen Sie die Videostream-Adresse der Kamera auf den Standardwert zurück</system:String>
<system:String x:Key="Text.PlayStopCameraVideoStream">Starten oder stoppen Sie den Videostream der Kamera</system:String>
<system:String x:Key="Text.CameraType">Kameratyp</system:String>
<system:String x:Key="Text.RemoteCameraType">Fernbedienung</system:String>

<!-- Non translatable -->
<system:String x:Key="Text.StarChar">*</system:String>
Expand Down
7 changes: 5 additions & 2 deletions CollimationCircles/Resources/Lang/en-US.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,11 @@
<system:String x:Key="Text.PayPalDonation">With this donation you will support me to continue developing of Collimation Circles application. Thank you!</system:String>
<system:String x:Key="Text.PayPalDonate">PayPal Donate</system:String>
<system:String x:Key="Text.CameraStreamTimeout">Video stream wait time timeout</system:String>
<system:String x:Key="Text.LibcameraVidCommand">Execute following command in Linux terminal before pressing Start button: libcamera-vid -t 0 --inline --nopreview --listen -o tcp://0.0.0.0:8080</system:String>

<system:String x:Key="Text.ResetCameraStreamAddress">Reset camera video stream address to default value</system:String>
<system:String x:Key="Text.PlayStopCameraVideoStream">Start or stop camera video stream</system:String>
<system:String x:Key="Text.CameraType">Camera type</system:String>
<system:String x:Key="Text.RemoteCameraType">Remote</system:String>

<!-- Non translatable -->
<system:String x:Key="Text.StarChar">*</system:String>
<system:String x:Key="Text.StarJson">json</system:String>
Expand Down
5 changes: 4 additions & 1 deletion CollimationCircles/Resources/Lang/fr-FR.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@
<system:String x:Key="Text.PayPalDonation">Avec ce don, vous me soutiendrez dans la poursuite du développement de l'application Collimation Circles. Merci!</system:String>
<system:String x:Key="Text.PayPalDonate">PayPal Donate</system:String>
<system:String x:Key="Text.CameraStreamTimeout">Délai d'attente du flux vidéo</system:String>
<system:String x:Key="Text.LibcameraVidCommand">Exécutez la commande suivante dans le terminal Linux avant d'appuyer sur le bouton Démarrer: libcamera-vid -t 0 --inline --nopreview --listen -o tcp://0.0.0.0:8080</system:String>
<system:String x:Key="Text.ResetCameraStreamAddress">Réinitialiser l'adresse du flux vidéo de la caméra à sa valeur par défaut</system:String>
<system:String x:Key="Text.PlayStopCameraVideoStream">Démarrer ou arrêter le flux vidéo de la caméra</system:String>
<system:String x:Key="Text.CameraType">Type de caméra</system:String>
<system:String x:Key="Text.RemoteCameraType">Télécommande</system:String>

<!-- Non translatable -->
<system:String x:Key="Text.StarChar">*</system:String>
Expand Down
5 changes: 4 additions & 1 deletion CollimationCircles/Resources/Lang/sl-SI.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,10 @@
<system:String x:Key="Text.PayPalDonation">S to donacijo me boste podprli pri nadaljnjem razvoju aplikacije Collimation Circles. Hvala vam!</system:String>
<system:String x:Key="Text.PayPalDonate">PayPal Donate</system:String>
<system:String x:Key="Text.CameraStreamTimeout">Čas čakanja na video tok</system:String>
<system:String x:Key="Text.LibcameraVidCommand">Izvedite naslednji ukaz v Linux terminalu, preden pritisnete gumb Start: libcamera-vid -t 0 --inline --nopreview --listen -o tcp://0.0.0.0:8080</system:String>
<system:String x:Key="Text.ResetCameraStreamAddress">Ponastavi naslov video toka kamere na privzeto vrednost</system:String>
<system:String x:Key="Text.PlayStopCameraVideoStream">Začne ali ustavi video tok kamere</system:String>
<system:String x:Key="Text.CameraType">Tip kamere</system:String>
<system:String x:Key="Text.RemoteCameraType">Oddaljen</system:String>

<!-- Non translatable -->
<system:String x:Key="Text.StarChar">*</system:String>
Expand Down
36 changes: 33 additions & 3 deletions CollimationCircles/Services/AppService.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using Newtonsoft.Json;
using Microsoft.Win32;
using Newtonsoft.Json;
using Octokit;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
Expand Down Expand Up @@ -214,7 +217,7 @@ public static Task<bool> IsPackageInstalled(string package)
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};
};

using Process process = new()
{
Expand Down Expand Up @@ -279,7 +282,7 @@ public static Task<bool> IsPackageInstalled(string package)
{
// Timed out.
logger.Warn($"Timeout '{fileName} {argStr}'");
tcs.TrySetResult((process.ExitCode, string.Empty, process));
tcs.TrySetResult((-1, string.Empty, process));
}
}
else
Expand Down Expand Up @@ -333,4 +336,31 @@ public static void OpenUrl(string url)

logger.Trace($"External url '{url}' opened");
}

public static string? FindVLC()
{
string vlcPath = "\\VideoLAN\\VLC\\vlc.exe";
string programFiles = Environment.ExpandEnvironmentVariables("%ProgramW6432%") + vlcPath;
string programFilesX86 = Environment.ExpandEnvironmentVariables("%ProgramFiles(x86)%") + vlcPath;

if (File.Exists(programFiles))
{
return programFiles;
}

if (File.Exists(programFilesX86))
{
return programFilesX86;
}

return null;
}

public static string? GetLocalIPAddress()
{
using Socket socket = new(AddressFamily.InterNetwork, SocketType.Dgram, 0);
socket.Connect("8.8.8.8", 65530);
IPEndPoint? endPoint = socket.LocalEndPoint as IPEndPoint;
return endPoint?.Address.ToString();
}
}
2 changes: 1 addition & 1 deletion CollimationCircles/ViewModels/SettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public partial class SettingsViewModel : BaseViewModel, IViewClosed

[JsonProperty]
[ObservableProperty]
private double settingsWindowWidth = 560;
private double settingsWindowWidth = 580;

[JsonProperty]
[ObservableProperty]
Expand Down
Loading

0 comments on commit b413b6e

Please sign in to comment.