This commit is contained in:
parent
de4c763f06
commit
db4a481037
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.1;net45;net46</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
|
||||
<GenerateDocumentFile>true</GenerateDocumentFile>
|
||||
<UseWpf>true</UseWpf>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
|
@ -16,6 +16,8 @@
|
|||
<PackageReference Include="CommonServiceLocator" Version="2.0.5" />
|
||||
<PackageReference Include="MvvmLightLibs" Version="5.4.1.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.5.1.20201226" />
|
||||
<PackageReference Include="OpenCvSharp4.WpfExtensions" Version="4.5.1.20201226" />
|
||||
<PackageReference Include="zlib.net" Version="1.0.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' != 'net45'">
|
||||
|
@ -48,6 +50,11 @@
|
|||
<HintPath>TRTC_SDK\Win32\lib\ManageLiteAV.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
|
||||
<PackageReference Include="OpenCvSharp4">
|
||||
<Version>4.5.1.20201226</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Exec Command="set Platform=Win64
SETLOCAL ENABLEDELAYEDEXPANSION
if $(PlatformName)==x86 ( 
set Platform=Win32
)
copy /Y "$(ProjectDir)TRTC_SDK\!Platform!\lib\*.dll" "$(ProjectDir)$(OutDir)"
ENDLOCAL" />
|
||||
</Target>
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"profiles": {
|
||||
"JianGongYun": {
|
||||
"commandName": "Project",
|
||||
"nativeDebugging": false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,246 @@
|
|||
<SolidColorBrush x:Key="Item.SelectedActive.foreground" Color="#396cd2" />
|
||||
<SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da" />
|
||||
|
||||
<!-- ScrollViewer 滚动条 -->
|
||||
<Style x:Key="ScrollBarThumb" TargetType="{x:Type Thumb}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="true"/>
|
||||
<Setter Property="IsTabStop" Value="false"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Thumb}">
|
||||
<Grid>
|
||||
<!--滚动条颜色-->
|
||||
<Border Background="#646465" CornerRadius="3"/>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style x:Key="HorizontalScrollBarPageButton" TargetType="{x:Type RepeatButton}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="true"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Focusable" Value="false"/>
|
||||
<Setter Property="IsTabStop" Value="false"/>
|
||||
<Setter Property="Opacity" Value="0.2"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type RepeatButton}">
|
||||
<Rectangle Fill="{TemplateBinding Background}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style x:Key="VerticalScrollBarPageButton" TargetType="{x:Type RepeatButton}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="true"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Focusable" Value="false"/>
|
||||
<Setter Property="IsTabStop" Value="false"/>
|
||||
<Setter Property="Opacity" Value="0.2"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type RepeatButton}">
|
||||
<Rectangle Fill="{TemplateBinding Background}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!--滚动条上下按钮-->
|
||||
<Style x:Key="VerticalScrollBarPageButton2" TargetType="{x:Type RepeatButton}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="true"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Focusable" Value="false"/>
|
||||
<Setter Property="IsTabStop" Value="false"/>
|
||||
<Setter Property="Opacity" Value="0"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type RepeatButton}">
|
||||
<Rectangle Fill="#90000000" Width="0" Height="0"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style x:Key="for_scrollbar" TargetType="{x:Type ScrollBar}">
|
||||
<Setter Property="Stylus.IsPressAndHoldEnabled" Value="false"/>
|
||||
<Setter Property="Stylus.IsFlicksEnabled" Value="false"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Margin" Value="0,1,1,6"/>
|
||||
<Setter Property="Width" Value="10"/>
|
||||
<Setter Property="MinWidth" Value="5"/>
|
||||
<Setter Property="Opacity" Value="0.2"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ScrollBar}">
|
||||
<Grid x:Name="Bg" SnapsToDevicePixels="true">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<RepeatButton Grid.Row="0" Style="{StaticResource VerticalScrollBarPageButton2}" Command="{x:Static ScrollBar.PageUpCommand}"/>
|
||||
<Track x:Name="PART_Track" Grid.Row="1" IsEnabled="{TemplateBinding IsMouseOver}" IsDirectionReversed="true">
|
||||
<Track.DecreaseRepeatButton>
|
||||
<RepeatButton Style="{StaticResource VerticalScrollBarPageButton}" Command="{x:Static ScrollBar.PageUpCommand}"/>
|
||||
</Track.DecreaseRepeatButton>
|
||||
<Track.IncreaseRepeatButton>
|
||||
<RepeatButton Style="{StaticResource VerticalScrollBarPageButton}" Command="{x:Static ScrollBar.PageDownCommand}"/>
|
||||
</Track.IncreaseRepeatButton>
|
||||
<Track.Thumb>
|
||||
<Thumb Style="{StaticResource ScrollBarThumb}"/>
|
||||
</Track.Thumb>
|
||||
</Track>
|
||||
<RepeatButton Grid.Row="2" Style="{StaticResource VerticalScrollBarPageButton2}" Command="{x:Static ScrollBar.PageDownCommand}"/>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Orientation" Value="Horizontal">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Margin" Value="1,0,6,1"/>
|
||||
<Setter Property="Height" Value="5"/>
|
||||
<Setter Property="MinHeight" Value="5"/>
|
||||
<Setter Property="Width" Value="Auto"/>
|
||||
<Setter Property="Opacity" Value="0.2"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ScrollBar}">
|
||||
<Grid x:Name="Bg" SnapsToDevicePixels="true">
|
||||
<Track x:Name="PART_Track" IsEnabled="{TemplateBinding IsMouseOver}">
|
||||
<Track.DecreaseRepeatButton>
|
||||
<RepeatButton Style="{StaticResource HorizontalScrollBarPageButton}" Command="{x:Static ScrollBar.PageLeftCommand}"/>
|
||||
</Track.DecreaseRepeatButton>
|
||||
<Track.IncreaseRepeatButton>
|
||||
<RepeatButton Style="{StaticResource HorizontalScrollBarPageButton}" Command="{x:Static ScrollBar.PageRightCommand}"/>
|
||||
</Track.IncreaseRepeatButton>
|
||||
<Track.Thumb>
|
||||
<Thumb Style="{StaticResource ScrollBarThumb}"/>
|
||||
</Track.Thumb>
|
||||
</Track>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style x:Key="for_scrollviewer"
|
||||
TargetType="{x:Type ScrollViewer}">
|
||||
<Setter Property="BorderBrush" Value="LightGray"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ScrollViewer}">
|
||||
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
|
||||
<Grid Background="{TemplateBinding Background}">
|
||||
<ScrollContentPresenter Cursor="{TemplateBinding Cursor}" Margin="{TemplateBinding Padding}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
|
||||
<ScrollBar x:Name="PART_VerticalScrollBar"
|
||||
HorizontalAlignment="Right"
|
||||
Maximum="{TemplateBinding ScrollableHeight}"
|
||||
Orientation="Vertical"
|
||||
Style="{StaticResource for_scrollbar}"
|
||||
ViewportSize="{TemplateBinding ViewportHeight}"
|
||||
Value="{TemplateBinding VerticalOffset}"
|
||||
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
|
||||
<ScrollBar x:Name="PART_HorizontalScrollBar"
|
||||
Maximum="{TemplateBinding ScrollableWidth}"
|
||||
Orientation="Horizontal"
|
||||
Style="{StaticResource for_scrollbar}"
|
||||
VerticalAlignment="Bottom"
|
||||
Value="{TemplateBinding HorizontalOffset}"
|
||||
ViewportSize="{TemplateBinding ViewportWidth}"
|
||||
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<EventTrigger RoutedEvent="ScrollChanged" >
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="PART_VerticalScrollBar"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.8"
|
||||
Duration="0:0:1"/>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="PART_VerticalScrollBar"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.2"
|
||||
Duration="0:0:1"
|
||||
BeginTime="0:0:1"/>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="PART_HorizontalScrollBar"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.8"
|
||||
Duration="0:0:1"/>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="PART_HorizontalScrollBar"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.2"
|
||||
Duration="0:0:1"
|
||||
BeginTime="0:0:1"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
<EventTrigger RoutedEvent="MouseEnter"
|
||||
SourceName="PART_VerticalScrollBar">
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="PART_VerticalScrollBar"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.8"
|
||||
Duration="0:0:0.7"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
<EventTrigger RoutedEvent="MouseLeave"
|
||||
SourceName="PART_VerticalScrollBar">
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="PART_VerticalScrollBar"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.2"
|
||||
Duration="0:0:0.7"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
<EventTrigger RoutedEvent="MouseEnter"
|
||||
SourceName="PART_HorizontalScrollBar">
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="PART_HorizontalScrollBar"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.8"
|
||||
Duration="0:0:0.7"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
<EventTrigger RoutedEvent="MouseLeave"
|
||||
SourceName="PART_HorizontalScrollBar">
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="PART_HorizontalScrollBar"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.2"
|
||||
Duration="0:0:0.7"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!--默认ScrollBar-->
|
||||
<Style TargetType="ScrollBar" BasedOn="{StaticResource for_scrollbar}"/>
|
||||
|
||||
<!--默认ScrollView-->
|
||||
<Style TargetType="ScrollViewer" BasedOn="{StaticResource for_scrollviewer}"/>
|
||||
|
||||
<Style x:Key="LeftIndicatorStyle" TargetType="{x:Type Metro:SegmentControl}">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="CornerRadius" Value="0" />
|
||||
|
@ -94,7 +334,27 @@
|
|||
<Setter Property="Foreground" Value="White"></Setter>
|
||||
<Setter Property="HorizontalAlignment" Value="Left"></Setter>
|
||||
<Setter Property="VerticalAlignment" Value="Center"></Setter>
|
||||
<Setter Property="Width" Value="100"></Setter>
|
||||
<Setter Property="Width" Value="125"></Setter>
|
||||
<Setter Property="TextAlignment" Value="Left"></Setter>
|
||||
</Style>
|
||||
|
||||
<!--图标按钮-->
|
||||
<Style TargetType="Button" x:Key="CusIconBtn">
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Name="border" BorderThickness="0" BorderBrush="Black">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Opacity" Value="0.8" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
|
@ -0,0 +1,16 @@
|
|||
<UserControl x:Class="JianGongYun.TRTC.Components.CountdownControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:JianGongYun.TRTC.Components" Loaded="UserControl_Loaded"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform x:Name="scale" ></ScaleTransform>
|
||||
</TransformGroup>
|
||||
</UserControl.RenderTransform>
|
||||
<Border CornerRadius="100" Background="#dddddd" Width="100" Height="100">
|
||||
<TextBlock x:Name="tb" Width="100" Height="100" Text="9" FontSize="85" TextAlignment="Center" FontWeight="Bold" FontFamily="FangSong" Foreground="Red"></TextBlock>
|
||||
</Border>
|
||||
</UserControl>
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace JianGongYun.TRTC.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// CountdownControl.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class CountdownControl : UserControl
|
||||
{
|
||||
private Grid grid = null;
|
||||
private Window wm;
|
||||
public CountdownControl(Grid _grid, Window _wm)
|
||||
{
|
||||
InitializeComponent();
|
||||
grid = _grid;
|
||||
wm = _wm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建动画执行对象
|
||||
/// </summary>
|
||||
private Storyboard sb = null;
|
||||
/// <summary>
|
||||
/// 给文本框赋值
|
||||
/// </summary>
|
||||
private string txtValue = string.Empty;
|
||||
public string TxtValue
|
||||
{
|
||||
get { return txtValue; }
|
||||
set { txtValue = value; this.tb.Text = txtValue; }
|
||||
}
|
||||
private void UserControl_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
//创建动画对象实例
|
||||
sb = new Storyboard();
|
||||
//ScaleX缩放动画
|
||||
//DoubleAnimation daX = new DoubleAnimation();
|
||||
//daX.Duration = TimeSpan.FromSeconds(0.6);
|
||||
//daX.From = 1.35;
|
||||
//daX.To = 1;
|
||||
//Storyboard.SetTarget(daX, this);
|
||||
//Storyboard.SetTargetProperty(daX, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
|
||||
////ScaleY缩放动画
|
||||
//DoubleAnimation daY = new DoubleAnimation();
|
||||
//daY.Duration = TimeSpan.FromSeconds(0.6);
|
||||
//daY.From = 1.35;
|
||||
//daY.To = 1;
|
||||
//Storyboard.SetTarget(daY, this);
|
||||
//Storyboard.SetTargetProperty(daY, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));
|
||||
//Opacity变换动画
|
||||
DoubleAnimation daO = new DoubleAnimation();
|
||||
daO.Duration = TimeSpan.FromSeconds(0.6);
|
||||
daO.From = 0;
|
||||
daO.To = 1;
|
||||
Storyboard.SetTarget(daO, this);
|
||||
Storyboard.SetTargetProperty(daO, new PropertyPath("(Opacity)"));
|
||||
//sb.Children.Add(daX);
|
||||
//sb.Children.Add(daY);
|
||||
sb.Children.Add(daO);
|
||||
|
||||
DoubleAnimation daTop2 = new DoubleAnimation();
|
||||
daTop2.BeginTime = TimeSpan.FromSeconds(0.7);
|
||||
daTop2.Duration = TimeSpan.FromSeconds(0.2);
|
||||
daTop2.EasingFunction = new BounceEase() { Bounces = 10, EasingMode = EasingMode.EaseInOut };
|
||||
Storyboard.SetTarget(daTop2, wm);
|
||||
Storyboard.SetTargetProperty(daTop2, new PropertyPath("(Top)"));
|
||||
sb.Children.Add(daTop2);
|
||||
sb.Completed += new EventHandler(sb_Completed);
|
||||
sb.Begin(this, true);
|
||||
}
|
||||
private void sb_Completed(object sender, EventArgs e)
|
||||
{
|
||||
//解除绑定
|
||||
sb.Remove(this);
|
||||
sb.Children.Clear();
|
||||
grid.Children.Clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<UserControl x:Class="JianGongYun.TRTC.Components.SytemGatherVolumeControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:JianGongYun.TRTC.Components"
|
||||
xmlns:Metro="clr-namespace:AduSkin.Controls.Metro;assembly=AduSkin"
|
||||
mc:Ignorable="d"
|
||||
Width="auto">
|
||||
</UserControl>
|
|
@ -1,26 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace JianGongYun.TRTC.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// SytemGatherVolumeControl.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class SytemGatherVolumeControl : UserControl
|
||||
{
|
||||
public SytemGatherVolumeControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,500 @@
|
|||
using ManageLiteAV;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace JianGongYun.TRTC.Components
|
||||
{
|
||||
public class TXLiteAVVideoView : Canvas, IDisposable
|
||||
{
|
||||
private bool mOccupy = false; // view 是否已被占用
|
||||
private bool mLocalView = false; // 是否为本地画面
|
||||
private bool mPause = false;
|
||||
private bool mFirstFrame = false;
|
||||
|
||||
private string mUserId;
|
||||
private TRTCVideoStreamType mStreamType;
|
||||
private TRTCVideoFillMode mRenderMode = TRTCVideoFillMode.TRTCVideoFillMode_Fit; // 0:填充,1:适应
|
||||
|
||||
private volatile FrameBufferInfo mArgbFrame = new FrameBufferInfo(); // 帧缓存
|
||||
|
||||
// 位图缓存,防止GC频繁
|
||||
private WriteableBitmap mWriteableBitmap;
|
||||
private Int32Rect mInt32Rect;
|
||||
private Pen mPen;
|
||||
|
||||
public TXLiteAVVideoView()
|
||||
{
|
||||
mPen = new Pen { Brush = Brushes.DarkGray, Thickness = 1 };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 View 绑定参数
|
||||
/// </summary>
|
||||
/// <param name="userId">需要渲染画面的 userId,如果是本地画面,则传空字符串。</param>
|
||||
/// <param name="type">渲染类型</param>
|
||||
/// <param name="engine">TRTCCloud 实例,用户注册视频数据回调。</param>
|
||||
/// <param name="local">渲染本地画面,SDK 返回的 userId 为""</param>
|
||||
/// <returns>true:绑定成功,false:绑定失败</returns>
|
||||
public bool RegEngine(string userId, TRTCVideoStreamType type, ITRTCCloud engine, bool local = false)
|
||||
{
|
||||
if (mOccupy) return false;
|
||||
mLocalView = local;
|
||||
mUserId = userId;
|
||||
mStreamType = type;
|
||||
int count = TXLiteAVVideoViewManager.GetInstance().Count;
|
||||
if (engine != null)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
engine.setLocalVideoRenderCallback(TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32,
|
||||
TRTCVideoBufferType.TRTCVideoBufferType_Buffer, TXLiteAVVideoViewManager.GetInstance());
|
||||
}
|
||||
if (!mLocalView)
|
||||
{
|
||||
engine.setRemoteVideoRenderCallback(userId, TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32,
|
||||
TRTCVideoBufferType.TRTCVideoBufferType_Buffer, TXLiteAVVideoViewManager.GetInstance());
|
||||
}
|
||||
}
|
||||
if (mLocalView)
|
||||
TXLiteAVVideoViewManager.GetInstance().AddView("", type, this);
|
||||
else
|
||||
TXLiteAVVideoViewManager.GetInstance().AddView(userId, type, this);
|
||||
lock (mArgbFrame)
|
||||
ReleaseBuffer(mArgbFrame);
|
||||
mOccupy = true;
|
||||
this.InvalidateVisual();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除 View 绑定参数
|
||||
/// </summary>
|
||||
/// <param name="engine">TRTCCloud 实例,用户注册视频数据回调。</param>
|
||||
public void RemoveEngine(ITRTCCloud engine)
|
||||
{
|
||||
if (mLocalView)
|
||||
TXLiteAVVideoViewManager.GetInstance().RemoveView("", mStreamType, this);
|
||||
else
|
||||
TXLiteAVVideoViewManager.GetInstance().RemoveView(mUserId, mStreamType, this);
|
||||
int count = TXLiteAVVideoViewManager.GetInstance().Count;
|
||||
if (engine != null)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
engine.setLocalVideoRenderCallback(TRTCVideoPixelFormat.TRTCVideoPixelFormat_Unknown,
|
||||
TRTCVideoBufferType.TRTCVideoBufferType_Unknown, null);
|
||||
}
|
||||
if (!mLocalView && !TXLiteAVVideoViewManager.GetInstance().HasUserId(mUserId))
|
||||
{
|
||||
engine.setRemoteVideoRenderCallback(mUserId, TRTCVideoPixelFormat.TRTCVideoPixelFormat_Unknown,
|
||||
TRTCVideoBufferType.TRTCVideoBufferType_Unknown, null);
|
||||
}
|
||||
}
|
||||
lock (mArgbFrame)
|
||||
ReleaseBuffer(mArgbFrame);
|
||||
mUserId = "";
|
||||
mOccupy = false;
|
||||
mLocalView = false;
|
||||
mFirstFrame = false;
|
||||
mRenderMode = TRTCVideoFillMode.TRTCVideoFillMode_Fit;
|
||||
this.InvalidateVisual();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 View 的渲染模式
|
||||
/// </summary>
|
||||
/// <param name="mode">渲染模式</param>
|
||||
public void SetRenderMode(TRTCVideoFillMode mode)
|
||||
{
|
||||
mRenderMode = mode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断 View 是否被占用
|
||||
/// </summary>
|
||||
/// <returns>true:当前 View 已被占用,false:当前 View 未被占用</returns>
|
||||
public bool IsViewOccupy()
|
||||
{
|
||||
return mOccupy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 暂停渲染,显示默认图片
|
||||
/// </summary>
|
||||
/// <param name="pause">是否暂停</param>
|
||||
public void SetPause(bool pause)
|
||||
{
|
||||
if (mPause != pause)
|
||||
{
|
||||
mPause = pause;
|
||||
if (mPause)
|
||||
{
|
||||
this.Background = new SolidColorBrush(Color.FromArgb(0xFF, 0x20, 0x20, 0x20));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Background = new SolidColorBrush(Color.FromArgb(0xFF, 0x00, 0x00, 0x00));
|
||||
// 避免刷新最后一帧数据
|
||||
lock (mArgbFrame)
|
||||
ReleaseBuffer(mArgbFrame);
|
||||
}
|
||||
this.InvalidateVisual();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除所有映射信息
|
||||
/// </summary>
|
||||
public static void RemoveAllRegEngine()
|
||||
{
|
||||
TXLiteAVVideoViewManager.GetInstance().RemoveAllView();
|
||||
}
|
||||
|
||||
public bool AppendVideoFrame(byte[] data, int width, int height, TRTCVideoPixelFormat videoFormat, TRTCVideoRotation rotation)
|
||||
{
|
||||
if (!mFirstFrame)
|
||||
mFirstFrame = true;
|
||||
if (mPause)
|
||||
return false;
|
||||
if (data == null || data.Length <= 0)
|
||||
return false;
|
||||
// data 数据有误
|
||||
if (videoFormat == TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32 && width * height * 4 != data.Length)
|
||||
return false;
|
||||
// 暂时不支持其他 YUV 类型
|
||||
if (videoFormat == TRTCVideoPixelFormat.TRTCVideoPixelFormat_I420 && width * height * 3 / 2 != data.Length)
|
||||
return false;
|
||||
|
||||
// 目前只实现了 BGRA32 的数据类型,如需其他类型请重写,并设置回调的数据类型
|
||||
if (videoFormat == TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32)
|
||||
{
|
||||
lock (mArgbFrame)
|
||||
{
|
||||
if (mArgbFrame.data == null || mArgbFrame.width != width || mArgbFrame.height != height)
|
||||
{
|
||||
ReleaseBuffer(mArgbFrame);
|
||||
mArgbFrame.width = width;
|
||||
mArgbFrame.height = height;
|
||||
mArgbFrame.data = new byte[data.Length];
|
||||
}
|
||||
Buffer.BlockCopy(data, 0, mArgbFrame.data, 0, (int)data.Length);
|
||||
mArgbFrame.newFrame = true;
|
||||
mArgbFrame.rotation = rotation;
|
||||
}
|
||||
}
|
||||
|
||||
// 回到主线程刷新当前画面
|
||||
this.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
this.InvalidateVisual();
|
||||
}));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnRender(DrawingContext dc)
|
||||
{
|
||||
bool needDrawFrame = true;
|
||||
if (mPause)
|
||||
needDrawFrame = false;
|
||||
if (mArgbFrame.data == null)
|
||||
needDrawFrame = false;
|
||||
if (!needDrawFrame)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (mArgbFrame)
|
||||
{
|
||||
if (mArgbFrame.data == null)
|
||||
return;
|
||||
if (mRenderMode == TRTCVideoFillMode.TRTCVideoFillMode_Fill)
|
||||
{
|
||||
RenderFillMode(dc, mArgbFrame.data, mArgbFrame.width, mArgbFrame.height, (int)mArgbFrame.rotation * 90);
|
||||
}
|
||||
else if (mRenderMode == TRTCVideoFillMode.TRTCVideoFillMode_Fit)
|
||||
{
|
||||
RenderFitMode(dc, mArgbFrame.data, mArgbFrame.width, mArgbFrame.height, (int)mArgbFrame.rotation * 90);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 渲染回调int width, int height, int rotation,WriteableBitmap image
|
||||
/// </summary>
|
||||
public event Action<int, int, int, WriteableBitmap> OnRenderVideoFrameHandler;
|
||||
|
||||
private void RenderFillMode(DrawingContext dc, byte[] data, int width, int height, int rotation)
|
||||
{
|
||||
int viewWidth = (int)this.ActualWidth, viewHeight = (int)this.ActualHeight;
|
||||
PixelFormat pixelFormat = PixelFormats.Pbgra32;
|
||||
int bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;
|
||||
int stride = bytesPerPixel * width;
|
||||
if (mWriteableBitmap == null || mWriteableBitmap.PixelWidth != width || mWriteableBitmap.PixelHeight != height)
|
||||
{
|
||||
mWriteableBitmap = new WriteableBitmap(width, height, 96, 96, pixelFormat, null);
|
||||
mInt32Rect = new Int32Rect(0, 0, width, height);
|
||||
}
|
||||
mWriteableBitmap.Lock();
|
||||
Marshal.Copy(data, 0, mWriteableBitmap.BackBuffer, data.Length);
|
||||
mWriteableBitmap.AddDirtyRect(mInt32Rect);
|
||||
mWriteableBitmap.Unlock();
|
||||
|
||||
//var tt = ConvertWriteableBitmapToBitmapImage(mWriteableBitmap);
|
||||
//OpenCvSharp.Mat result = OpenCvSharp.Extensions.BitmapConverter.ToMat(tt);
|
||||
//tt.Dispose();
|
||||
//result.Create(mWriteableBitmap.PixelHeight, mWriteableBitmap.PixelWidth, OpenCvSharp.MatType.CV_8UC4, 4);
|
||||
//mWriteableBitmap.CopyPixels(Int32Rect.Empty, result.Data, data.Length, 4);
|
||||
//LiveClassroom.bbb.Enqueue(result);
|
||||
//result.ImWrite($"d:\\{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.png");
|
||||
//var a = ConvertWriteableBitmapToBitmapImage(mWriteableBitmap);
|
||||
//a.Save($"d:\\{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.png");
|
||||
OnRenderVideoFrameHandler?.Invoke(width, height, rotation, mWriteableBitmap);
|
||||
|
||||
ImageBrush brush = new ImageBrush(mWriteableBitmap);
|
||||
if (rotation > 0)
|
||||
{
|
||||
Matrix transform = Matrix.Identity;
|
||||
double scale = (double)viewWidth / (double)viewHeight;
|
||||
if (rotation == 90 || rotation == 270)
|
||||
transform.ScaleAt(scale, scale, 0.5, 0.5);
|
||||
transform.RotateAt(rotation, 0.5, 0.5);
|
||||
brush.RelativeTransform = new MatrixTransform(transform);
|
||||
}
|
||||
brush.Stretch = Stretch.UniformToFill;
|
||||
Rect rect = new Rect(0, 0, viewWidth, viewHeight);
|
||||
dc.DrawRectangle(brush, mPen, rect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void RenderFitMode(DrawingContext dc, byte[] data, int width, int height, int rotation)
|
||||
{
|
||||
int viewWidth = (int)this.ActualWidth, viewHeight = (int)this.ActualHeight;
|
||||
PixelFormat pixelFormat = PixelFormats.Pbgra32;
|
||||
int bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;
|
||||
int stride = bytesPerPixel * width;
|
||||
if (mWriteableBitmap == null || mWriteableBitmap.PixelWidth != width || mWriteableBitmap.PixelHeight != height)
|
||||
{
|
||||
mWriteableBitmap = new WriteableBitmap(width, height, 96, 96, pixelFormat, null);
|
||||
//Mat result = new Mat();
|
||||
//result.Create(mWriteableBitmap.PixelHeight, mWriteableBitmap.PixelWidth, MatType.CV_8U, 4);
|
||||
//mWriteableBitmap.CopyPixels(Int32Rect.Empty, result.Data, (int)result.Step() * result.Rows, (int)result.Step());
|
||||
mInt32Rect = new Int32Rect(0, 0, width, height);
|
||||
}
|
||||
mWriteableBitmap.Lock();
|
||||
Marshal.Copy(data, 0, mWriteableBitmap.BackBuffer, data.Length);
|
||||
mWriteableBitmap.AddDirtyRect(mInt32Rect);
|
||||
mWriteableBitmap.Unlock();
|
||||
|
||||
OnRenderVideoFrameHandler?.Invoke(width, height, rotation, mWriteableBitmap);
|
||||
|
||||
ImageBrush brush = new ImageBrush(mWriteableBitmap);
|
||||
if (rotation > 0)
|
||||
{
|
||||
Matrix transform = Matrix.Identity;
|
||||
double scale = (double)viewHeight / (double)viewWidth;
|
||||
if (rotation == 90 || rotation == 270)
|
||||
transform.ScaleAt(1, scale, 0.5, 0.5);
|
||||
transform.RotateAt(rotation, 0.5, 0.5);
|
||||
brush.RelativeTransform = new MatrixTransform(transform);
|
||||
}
|
||||
brush.Stretch = Stretch.Uniform;
|
||||
Rect rect = new Rect(0, 0, viewWidth, viewHeight);
|
||||
dc.DrawRectangle(brush, mPen, rect);
|
||||
}
|
||||
|
||||
private void ReleaseBuffer(FrameBufferInfo info)
|
||||
{
|
||||
if (info.data != null)
|
||||
info.data = null;
|
||||
info.width = 0;
|
||||
info.height = 0;
|
||||
info.newFrame = false;
|
||||
info.rotation = TRTCVideoRotation.TRTCVideoRotation0;
|
||||
}
|
||||
|
||||
#region Dispose
|
||||
private bool disposed = false;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed) return;
|
||||
if (disposing)
|
||||
{
|
||||
ReleaseBuffer(mArgbFrame);
|
||||
mWriteableBitmap = null;
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
~TXLiteAVVideoView()
|
||||
{
|
||||
this.Dispose(false);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class TXLiteAVVideoViewManager : ITRTCVideoRenderCallback
|
||||
{
|
||||
private volatile Dictionary<string, TXLiteAVVideoView> mMapViews;
|
||||
|
||||
public static TXLiteAVVideoViewManager sInstance;
|
||||
|
||||
private static Object mLocker = new Object();
|
||||
|
||||
public static TXLiteAVVideoViewManager GetInstance()
|
||||
{
|
||||
if (sInstance == null)
|
||||
{
|
||||
lock (mLocker)
|
||||
{
|
||||
if (sInstance == null)
|
||||
sInstance = new TXLiteAVVideoViewManager();
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private TXLiteAVVideoViewManager()
|
||||
{
|
||||
mMapViews = new Dictionary<string, TXLiteAVVideoView>();
|
||||
}
|
||||
|
||||
private string GetKey(string userId, TRTCVideoStreamType type)
|
||||
{
|
||||
return String.Format("{0}_{1}", userId, type);
|
||||
}
|
||||
|
||||
// 主要用于判断当前 user 是否还有存在流画面,存在则不移除监听。
|
||||
public bool HasUserId(string userId)
|
||||
{
|
||||
bool exit = false;
|
||||
lock (mMapViews)
|
||||
{
|
||||
exit = mMapViews.ContainsKey(GetKey(userId, TRTCVideoStreamType.TRTCVideoStreamTypeBig)) ||
|
||||
mMapViews.ContainsKey(GetKey(userId, TRTCVideoStreamType.TRTCVideoStreamTypeSub));
|
||||
}
|
||||
return exit;
|
||||
}
|
||||
|
||||
public void AddView(string userId, TRTCVideoStreamType type, TXLiteAVVideoView view)
|
||||
{
|
||||
lock (mMapViews)
|
||||
{
|
||||
bool find = false;
|
||||
foreach (var item in mMapViews)
|
||||
{
|
||||
if (item.Key.Equals(GetKey(userId, type)))
|
||||
{
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!find)
|
||||
{
|
||||
mMapViews.Add(GetKey(userId, type), view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveView(string userId, TRTCVideoStreamType type, TXLiteAVVideoView view)
|
||||
{
|
||||
lock (mMapViews)
|
||||
{
|
||||
foreach (var item in mMapViews.ToList())
|
||||
{
|
||||
if (item.Key.Equals(GetKey(userId, type)))
|
||||
{
|
||||
if (item.Value != null)
|
||||
{
|
||||
item.Value.Dispose();
|
||||
}
|
||||
mMapViews.Remove(item.Key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAllView()
|
||||
{
|
||||
lock (mMapViews)
|
||||
mMapViews.Clear();
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (mMapViews)
|
||||
return mMapViews.Count;
|
||||
}
|
||||
}
|
||||
|
||||
//public event Action<string, TRTCVideoStreamType, TRTCVideoFrame> OnRenderVideoFrameHandler;
|
||||
/// <summary>
|
||||
/// 自定义渲染回调,只能存在一个回调
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="streamType"></param>
|
||||
/// <param name="frame"></param>
|
||||
public void onRenderVideoFrame(string userId, TRTCVideoStreamType streamType, TRTCVideoFrame frame)
|
||||
{
|
||||
//OnRenderVideoFrameHandler?.Invoke(userId, streamType, frame);
|
||||
// 大小视频是占一个视频位,底层支持动态切换。
|
||||
if (streamType == TRTCVideoStreamType.TRTCVideoStreamTypeSmall)
|
||||
streamType = TRTCVideoStreamType.TRTCVideoStreamTypeBig;
|
||||
TXLiteAVVideoView view = null;
|
||||
lock (mMapViews)
|
||||
{
|
||||
foreach (var item in mMapViews)
|
||||
{
|
||||
if (item.Key.Equals(GetKey(userId, streamType)) && item.Value != null)
|
||||
{
|
||||
view = item.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (view != null)
|
||||
view.AppendVideoFrame(frame.data, (int)frame.width, (int)frame.height, frame.videoFormat, frame.rotation);
|
||||
}
|
||||
}
|
||||
|
||||
class FrameBufferInfo
|
||||
{
|
||||
public byte[] data { get; set; }
|
||||
|
||||
public int width { get; set; }
|
||||
|
||||
public int height { get; set; }
|
||||
|
||||
public bool newFrame { get; set; }
|
||||
|
||||
public TRTCVideoRotation rotation { get; set; }
|
||||
|
||||
public FrameBufferInfo()
|
||||
{
|
||||
rotation = TRTCVideoRotation.TRTCVideoRotation0;
|
||||
newFrame = false;
|
||||
width = 0;
|
||||
height = 0;
|
||||
data = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,19 @@
|
|||
using JianGongYun.TRTC.Models;
|
||||
using JianGongYun.TRTC.Components;
|
||||
using JianGongYun.TRTC.Models;
|
||||
using JianGongYun.TRTC.Utils;
|
||||
using JianGongYun.TRTC.ViewModels;
|
||||
using JianGongYun.TRTC.Windows;
|
||||
using ManageLiteAV;
|
||||
using OpenCvSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Window = System.Windows.Window;
|
||||
|
||||
namespace JianGongYun.TRTC
|
||||
{
|
||||
|
@ -52,7 +60,6 @@ namespace JianGongYun.TRTC
|
|||
CurrentLiveWindow = new LiveWindow();
|
||||
CurrentLiveWindow.Closed += CurrentLiveWindow_Closed;
|
||||
|
||||
|
||||
lTRTCCloud = ITRTCCloud.getTRTCShareInstance();//创建TRTC实例
|
||||
var roomPars = new TRTCParams
|
||||
{
|
||||
|
@ -66,20 +73,102 @@ namespace JianGongYun.TRTC
|
|||
lTRTCCloud.enterRoom(ref roomPars, TRTCAppScene.TRTCAppSceneLIVE);//创建房间
|
||||
|
||||
//设备
|
||||
var settingViewMode = ViewModels.SettingWindowViewModel.GetInstance();
|
||||
//var settingViewMode = ViewModels.SettingWindowViewModel.GetInstance();
|
||||
lTXDeviceManager = lTRTCCloud.getDeviceManager();
|
||||
var currentMic = settingViewMode.CurrentMic;//麦克风
|
||||
var currentMic = settingWindowViewModel.CurrentMic;//麦克风
|
||||
if (!string.IsNullOrEmpty(currentMic))
|
||||
{
|
||||
var res = lTXDeviceManager.setCurrentDevice(TRTCDeviceType.TXMediaDeviceTypeMic, currentMic);
|
||||
Console.WriteLine($"设置麦克风:{res}");
|
||||
}
|
||||
lTXDeviceManager.setCurrentDeviceVolume(TRTCDeviceType.TXMediaDeviceTypeMic, settingWindowViewModel.MicVolume);//麦克风采集音量
|
||||
lTRTCCloud.setSystemAudioLoopbackVolume(settingWindowViewModel.SytemGatherVolume);//系统声音采集音量
|
||||
if (settingWindowViewModel.AudioSource == "2")
|
||||
{
|
||||
lTRTCCloud.startSystemAudioLoopback("");
|
||||
}
|
||||
else
|
||||
{
|
||||
lTRTCCloud.stopSystemAudioLoopback();
|
||||
}
|
||||
var encParams = settingWindowViewModel.EncParams;
|
||||
var qosParams = settingWindowViewModel.QosParams;
|
||||
var renderParams = settingWindowViewModel.RenderParams;
|
||||
lTRTCCloud.setVideoEncoderParam(ref encParams);
|
||||
lTRTCCloud.setNetworkQosParam(ref qosParams);
|
||||
lTRTCCloud.setLocalRenderParams(ref renderParams);
|
||||
//设备完结
|
||||
|
||||
|
||||
callerWindow.Hide();//隐藏调用窗口
|
||||
CurrentLiveWindow.Show();
|
||||
}
|
||||
|
||||
|
||||
private static SettingWindowViewModel settingWindowViewModel = SettingWindowViewModel.GetInstance();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 视频画面
|
||||
/// </summary>
|
||||
private static Dictionary<string, TXLiteAVVideoView> VideoViews = new Dictionary<string, TXLiteAVVideoView>();
|
||||
/// <summary>
|
||||
/// 启动摄像头
|
||||
/// </summary>
|
||||
/// <param name="parent">视频容器</param>
|
||||
public static void StartVideoMain(Panel parent)
|
||||
{
|
||||
lTRTCCloud.startLocalPreview(IntPtr.Zero);
|
||||
var liveWinMode = CurrentLiveWindow.DataContext as LiveWindowViewModel;
|
||||
liveWinMode.CameraRunning = true;
|
||||
AddCustomVideoView(parent, CurrentClassroomEntity.TeacherId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, true);
|
||||
}
|
||||
/// <summary>
|
||||
/// 添加自定义渲染 View 并绑定渲染回调
|
||||
/// </summary>
|
||||
private static void AddCustomVideoView(Panel parent, string userId, TRTCVideoStreamType streamType, bool local = false)
|
||||
{
|
||||
TXLiteAVVideoView videoView = new TXLiteAVVideoView();
|
||||
videoView.RegEngine(userId, streamType, lTRTCCloud, local);
|
||||
videoView.SetRenderMode(settingWindowViewModel.RenderParams.fillMode);
|
||||
videoView.Width = parent.ActualWidth;
|
||||
videoView.Height = parent.ActualHeight;
|
||||
parent.Children.Add(videoView);
|
||||
string key = string.Format("{0}_{1}", userId, streamType);
|
||||
VideoViews.Add(key, videoView);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除自定义渲染 View 并解绑渲染回调
|
||||
/// </summary>
|
||||
private static void RemoveCustomVideoView(Panel parent, string userId, TRTCVideoStreamType streamType, bool local = false)
|
||||
{
|
||||
TXLiteAVVideoView videoView = null;
|
||||
string key = string.Format("{0}_{1}", userId, streamType);
|
||||
if (VideoViews.TryGetValue(key, out videoView))
|
||||
{
|
||||
videoView.RemoveEngine(lTRTCCloud);
|
||||
parent.Children.Remove(videoView);
|
||||
VideoViews.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重启音频录制
|
||||
/// </summary>
|
||||
public static void RestartAudio() { }
|
||||
/// <summary>
|
||||
/// 重设主视频(摄像头)
|
||||
/// </summary>
|
||||
public static void ResetVideoMain() { }
|
||||
/// <summary>
|
||||
/// 重设主视频(摄像头)网络
|
||||
/// </summary>
|
||||
public static void ResetVideoMainQos() { }
|
||||
/// <summary>
|
||||
/// 重设副视频(录屏)
|
||||
/// </summary>
|
||||
public static void ResetVideoSub() { }
|
||||
|
||||
|
||||
private static void CurrentLiveWindow_Closed(object sender, EventArgs e)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace JianGongYun.TRTC.Models
|
||||
{
|
||||
public enum LiveTypeEnum
|
||||
{
|
||||
CameraAndScreen = 0,
|
||||
OnlyScreen,
|
||||
OnlyCamera,
|
||||
OnlyAudio,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using JianGongYun.TRTC.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace JianGongYun.TRTC
|
||||
{
|
||||
public class LiveTypeToBoolConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value.ToString() == parameter.ToString();
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
bool isChecked = (bool)value;
|
||||
if (!isChecked)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return (LiveTypeEnum)Enum.Parse(typeof(LiveTypeEnum), parameter.ToString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace JianGongYun.TRTC
|
||||
{
|
||||
/// <summary>
|
||||
/// 把bool转换为相反的控件显示状态(内置的BooleanToVisibilityConverter的true为显示false为隐藏)
|
||||
/// </summary>
|
||||
public class UnBooleanToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
bool flag = false;
|
||||
if (value is bool)
|
||||
{
|
||||
flag = (bool)value;
|
||||
}
|
||||
else if (value is bool?)
|
||||
{
|
||||
bool? nullable = (bool?)value;
|
||||
flag = nullable.HasValue ? nullable.Value : false;
|
||||
}
|
||||
return (flag ? Visibility.Hidden : Visibility.Visible);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using OpenCvSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace JianGongYun.TRTC.Utils
|
||||
{
|
||||
public static class WriteableBitmapToMat
|
||||
{
|
||||
/// <summary>
|
||||
/// WriteableBitmap转Mat
|
||||
/// </summary>
|
||||
/// <param name="writeableBitmap"></param>
|
||||
/// <returns></returns>
|
||||
public static Mat ToMat(this WriteableBitmap writeableBitmap)
|
||||
{
|
||||
using (MemoryStream outStream = new MemoryStream())
|
||||
{
|
||||
BitmapEncoder enc = new JpegBitmapEncoder();
|
||||
enc.Frames.Add(BitmapFrame.Create(writeableBitmap));
|
||||
enc.Save(outStream);
|
||||
using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(outStream))
|
||||
{
|
||||
var mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmp);
|
||||
return mat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
using System;
|
||||
using JianGongYun.TRTC.Models;
|
||||
using ManageLiteAV;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace JianGongYun.TRTC.ViewModels
|
||||
{
|
||||
|
@ -44,6 +47,15 @@ namespace JianGongYun.TRTC.ViewModels
|
|||
set
|
||||
{
|
||||
_IsLive = value;
|
||||
if (value)//开始直播,清空时间并开始计时
|
||||
{
|
||||
_LiveTimeCount = new DateTime(1970, 1, 1, 0, 0, 0);
|
||||
timer.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
timer.Stop();
|
||||
}
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("IsLive"));
|
||||
|
@ -55,5 +67,147 @@ namespace JianGongYun.TRTC.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public LiveWindowViewModel()
|
||||
{
|
||||
timer = new DispatcherTimer();
|
||||
timer.Interval = TimeSpan.FromSeconds(1);
|
||||
timer.Tick += new EventHandler((a, b) => LiveTimeCount = "");
|
||||
}
|
||||
/// <summary>
|
||||
/// 直播计时器
|
||||
/// </summary>
|
||||
private DispatcherTimer timer = null;
|
||||
private DateTime _LiveTimeCount;
|
||||
public string LiveTimeCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _LiveTimeCount.ToString("HH:mm:ss");
|
||||
}
|
||||
set
|
||||
{
|
||||
_LiveTimeCount = _LiveTimeCount.AddSeconds(1);
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("LiveTimeCount"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 直播类型
|
||||
/// </summary>
|
||||
private LiveTypeEnum _LiveType = LiveTypeEnum.OnlyAudio;
|
||||
public LiveTypeEnum LiveType
|
||||
{
|
||||
set
|
||||
{
|
||||
_LiveType = value;
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("LiveType"));
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return _LiveType;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 摄像头采集中
|
||||
/// </summary>
|
||||
private bool _CameraRunning = false;
|
||||
public bool CameraRunning
|
||||
{
|
||||
set
|
||||
{
|
||||
_CameraRunning = value;
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("CameraRunning"));
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return _CameraRunning;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 屏幕分享中
|
||||
/// </summary>
|
||||
private bool _ScreenRunning = false;
|
||||
public bool ScreenRunning
|
||||
{
|
||||
set
|
||||
{
|
||||
_ScreenRunning = value;
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRunning"));
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return _ScreenRunning;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 麦克风使用中
|
||||
/// </summary>
|
||||
private bool _MicRunning = false;
|
||||
public bool MicRunning
|
||||
{
|
||||
set
|
||||
{
|
||||
_MicRunning = value;
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("MicRunning"));
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return _MicRunning;
|
||||
}
|
||||
}
|
||||
|
||||
private SIZE thumbSize = new SIZE { cx = 300, cy = 200 };
|
||||
private SIZE iconSize = new SIZE { cx = 50, cy = 50 };
|
||||
private ObservableCollection<TRTCScreenCaptureSourceInfo> _LiveScreens = new ObservableCollection<TRTCScreenCaptureSourceInfo>();
|
||||
/// <summary>
|
||||
/// 可分享桌面
|
||||
/// </summary>
|
||||
public ObservableCollection<TRTCScreenCaptureSourceInfo> LiveScreens
|
||||
{
|
||||
get
|
||||
{
|
||||
_LiveScreens.Clear();
|
||||
var temp = LiveClassroom.lTRTCCloud.getScreenCaptureSources(ref thumbSize, ref iconSize);
|
||||
var count = temp.getCount();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
_LiveScreens.Add(temp.getSourceInfo(i));
|
||||
}
|
||||
temp.release();
|
||||
return _LiveScreens;
|
||||
}
|
||||
}
|
||||
|
||||
private IntPtr _CurrentShareScreen;
|
||||
public IntPtr CurrentShareScreen
|
||||
{
|
||||
get { return _CurrentShareScreen; }
|
||||
set
|
||||
{
|
||||
_CurrentShareScreen = value;
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("CurrentShareScreen"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ using System.Linq;
|
|||
using System.Windows.Controls;
|
||||
using JianGongYun.TRTC.Components;
|
||||
using System.Windows;
|
||||
using ManageLiteAV;
|
||||
|
||||
namespace JianGongYun.TRTC.ViewModels
|
||||
{
|
||||
|
@ -40,7 +41,7 @@ namespace JianGongYun.TRTC.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
#region 麦克风
|
||||
#region 音频属性
|
||||
/// <summary>
|
||||
/// 集合,实时获取
|
||||
/// </summary>
|
||||
|
@ -140,10 +141,6 @@ namespace JianGongYun.TRTC.ViewModels
|
|||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 音频来源
|
||||
|
||||
/// <summary>
|
||||
/// 音频来源
|
||||
/// </summary>
|
||||
|
@ -169,7 +166,7 @@ namespace JianGongYun.TRTC.ViewModels
|
|||
storage.SetValue(INI_ROOT_KEY, INI_KEY_AUDIO_SOURCE, value);//生成保存本地
|
||||
if (_AudioSource == "1")//只采集麦克风,关闭系统音采集
|
||||
{
|
||||
ShowSytemGatherSlider = Visibility.Hidden;
|
||||
ShowSytemGatherSlider = Visibility.Collapsed;
|
||||
LiveClassroom.lTRTCCloud.stopSystemAudioLoopback();
|
||||
}
|
||||
else if (_AudioSource == "2")//麦和系统音,开启采集系统音
|
||||
|
@ -187,18 +184,18 @@ namespace JianGongYun.TRTC.ViewModels
|
|||
/// <summary>
|
||||
/// 是否显示系统采集滑动条
|
||||
/// </summary>
|
||||
private Visibility _ShowSytemGatherSlider = Visibility.Hidden;
|
||||
private Visibility _ShowSytemGatherSlider = Visibility.Collapsed;
|
||||
public Visibility ShowSytemGatherSlider
|
||||
{
|
||||
get
|
||||
{
|
||||
if (AudioSource=="2")
|
||||
if (AudioSource == "2")
|
||||
{
|
||||
_ShowSytemGatherSlider = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ShowSytemGatherSlider = Visibility.Hidden;
|
||||
_ShowSytemGatherSlider = Visibility.Collapsed;
|
||||
}
|
||||
return _ShowSytemGatherSlider;
|
||||
}
|
||||
|
@ -246,6 +243,397 @@ namespace JianGongYun.TRTC.ViewModels
|
|||
|
||||
#endregion
|
||||
|
||||
#region 录屏属性
|
||||
|
||||
/// <summary>
|
||||
/// 视频帧率(fps)
|
||||
/// </summary>
|
||||
private string _ScreenRecordingFps = "60";
|
||||
public string ScreenRecordingFps
|
||||
{
|
||||
get
|
||||
{
|
||||
var screenRecordingFps = storage.GetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_FPS);//本地缓存
|
||||
if (string.IsNullOrEmpty(screenRecordingFps))
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_FPS, _ScreenRecordingFps);//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_ScreenRecordingFps = screenRecordingFps;
|
||||
}
|
||||
return _ScreenRecordingFps;
|
||||
}
|
||||
set
|
||||
{
|
||||
_ScreenRecordingFps = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_FPS, value);//生成保存本地
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRecordingFps"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 音频码率
|
||||
/// </summary>
|
||||
private string _ScreenRecordingAudioBitrate = "320000";
|
||||
public string ScreenRecordingAudioBitrate
|
||||
{
|
||||
get
|
||||
{
|
||||
var screenRecordingAudioBitrate = storage.GetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_AUDIO_BITRATE);//本地缓存
|
||||
if (string.IsNullOrEmpty(screenRecordingAudioBitrate))
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_AUDIO_BITRATE, _ScreenRecordingAudioBitrate);//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_ScreenRecordingAudioBitrate = screenRecordingAudioBitrate;
|
||||
}
|
||||
return _ScreenRecordingAudioBitrate;
|
||||
}
|
||||
set
|
||||
{
|
||||
_ScreenRecordingAudioBitrate = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_AUDIO_BITRATE, value);//生成保存本地
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRecordingAudioBitrate"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 音频采样率
|
||||
/// </summary>
|
||||
private string _ScreenRecordingAudioFreq = "48000";
|
||||
public string ScreenRecordingAudioFreq
|
||||
{
|
||||
get
|
||||
{
|
||||
var screenRecordingAudioFreq = storage.GetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_AUDIO_FREQ);//本地缓存
|
||||
if (string.IsNullOrEmpty(screenRecordingAudioFreq))
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_AUDIO_FREQ, _ScreenRecordingAudioFreq);//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_ScreenRecordingAudioFreq = screenRecordingAudioFreq;
|
||||
}
|
||||
return _ScreenRecordingAudioFreq;
|
||||
}
|
||||
set
|
||||
{
|
||||
_ScreenRecordingAudioFreq = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_AUDIO_FREQ, value);//生成保存本地
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRecordingAudioFreq"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编码级别
|
||||
/// </summary>
|
||||
private string _ScreenRecordingProfileLevel = "-profile:v high -level 5.1";
|
||||
public string ScreenRecordingProfileLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
var screenRecordingProfileLevel = storage.GetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_PROFILE_LEVEL);//本地缓存
|
||||
if (string.IsNullOrEmpty(screenRecordingProfileLevel))
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_PROFILE_LEVEL, _ScreenRecordingProfileLevel);//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_ScreenRecordingProfileLevel = screenRecordingProfileLevel;
|
||||
}
|
||||
return _ScreenRecordingProfileLevel;
|
||||
}
|
||||
set
|
||||
{
|
||||
_ScreenRecordingProfileLevel = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_PROFILE_LEVEL, value);//生成保存本地
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRecordingProfileLevel"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 录制倒计时
|
||||
/// </summary>
|
||||
private int _ScreenRecordingCountdown = 3;
|
||||
public int ScreenRecordingCountdown
|
||||
{
|
||||
get
|
||||
{
|
||||
var screenRecordingCountdown = storage.GetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_COUNTDOWN);//本地缓存
|
||||
if (string.IsNullOrEmpty(screenRecordingCountdown))
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_COUNTDOWN, _ScreenRecordingCountdown.ToString());//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_ScreenRecordingCountdown = int.Parse(screenRecordingCountdown);
|
||||
}
|
||||
return _ScreenRecordingCountdown;
|
||||
}
|
||||
set
|
||||
{
|
||||
_ScreenRecordingCountdown = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_COUNTDOWN, value.ToString());//生成保存本地
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRecordingCountdown"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 视频保存路径
|
||||
/// </summary>
|
||||
private string _ScreenRecordingDir;
|
||||
public string ScreenRecordingDir
|
||||
{
|
||||
get
|
||||
{
|
||||
var screenRecordingDir = storage.GetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_DIR);//本地缓存
|
||||
if (string.IsNullOrEmpty(screenRecordingDir))
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_DIR, _ScreenRecordingDir);//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_ScreenRecordingDir = screenRecordingDir;
|
||||
}
|
||||
return _ScreenRecordingDir;
|
||||
}
|
||||
set
|
||||
{
|
||||
_ScreenRecordingDir = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_DIR, value.ToString());//生成保存本地
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRecordingDir"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 直播设置属性
|
||||
|
||||
/// <summary>
|
||||
/// 音频质量
|
||||
/// </summary>
|
||||
private TRTCAudioQuality _LiveAudioLevel = TRTCAudioQuality.TRTCAudioQualityDefault;
|
||||
public TRTCAudioQuality LiveAudioLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
var liveAudioLevel = storage.GetValue(INI_ROOT_KEY, INI_KEY_LIVE_AUDIO_LEVEL);//本地缓存
|
||||
if (string.IsNullOrEmpty(liveAudioLevel))
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_AUDIO_LEVEL, _LiveAudioLevel.ToString());//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_LiveAudioLevel = (TRTCAudioQuality)Enum.Parse(typeof(TRTCAudioQuality), liveAudioLevel);
|
||||
}
|
||||
return _LiveAudioLevel;
|
||||
}
|
||||
set
|
||||
{
|
||||
_LiveAudioLevel = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_AUDIO_LEVEL, value.ToString());//生成保存本地
|
||||
LiveClassroom.RestartAudio();//重启音频
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("LiveAudioLevel"));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 摄像画面帧率
|
||||
/// </summary>
|
||||
private uint _LiveMainFps = 24;
|
||||
public uint LiveMainFps
|
||||
{
|
||||
get
|
||||
{
|
||||
var liveMainFps = storage.GetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_FPS);//本地缓存
|
||||
if (string.IsNullOrEmpty(liveMainFps))
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_FPS, _LiveMainFps.ToString());//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_LiveMainFps = uint.Parse(liveMainFps);
|
||||
}
|
||||
return _LiveMainFps;
|
||||
}
|
||||
set
|
||||
{
|
||||
_LiveMainFps = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_FPS, value.ToString());//生成保存本地
|
||||
LiveClassroom.ResetVideoMain();//重设参数
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("LiveMainFps"));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 摄像画面码率
|
||||
/// </summary>
|
||||
private uint _LiveMainBitrate = 1600;
|
||||
public uint LiveMainBitrate
|
||||
{
|
||||
get
|
||||
{
|
||||
var liveMainBitrate = storage.GetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_BITTRATE);//本地缓存
|
||||
if (string.IsNullOrEmpty(liveMainBitrate))
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_BITTRATE, _LiveMainBitrate.ToString());//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_LiveMainBitrate = uint.Parse(liveMainBitrate);
|
||||
}
|
||||
return _LiveMainBitrate;
|
||||
}
|
||||
set
|
||||
{
|
||||
_LiveMainBitrate = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_BITTRATE, value.ToString());//生成保存本地
|
||||
LiveClassroom.ResetVideoMain();//重设参数
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("LiveMainBitrate"));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 摄像画面级别
|
||||
/// </summary>
|
||||
private TRTCVideoQosPreference _LiveMainLevel = TRTCVideoQosPreference.TRTCVideoQosPreferenceClear;
|
||||
public TRTCVideoQosPreference LiveMainLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
var liveMainLevel = storage.GetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_LEVEL);//本地缓存
|
||||
if (string.IsNullOrEmpty(liveMainLevel))
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_LEVEL, _LiveMainLevel.ToString());//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_LiveMainLevel = (TRTCVideoQosPreference)Enum.Parse(typeof(TRTCVideoQosPreference), liveMainLevel);
|
||||
}
|
||||
return _LiveMainLevel;
|
||||
}
|
||||
set
|
||||
{
|
||||
_LiveMainLevel = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_LEVEL, value.ToString());//生成保存本地
|
||||
LiveClassroom.ResetVideoMainQos();//重设参数
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("LiveMainLevel"));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 屏幕分享帧率
|
||||
/// </summary>
|
||||
private uint _LiveSubFps = 24;
|
||||
public uint LiveSubFps
|
||||
{
|
||||
get
|
||||
{
|
||||
var liveSubFps = storage.GetValue(INI_ROOT_KEY, INI_KEY_LIVE_SUB_FPS);//本地缓存
|
||||
if (string.IsNullOrEmpty(liveSubFps))
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_SUB_FPS, _LiveSubFps.ToString());//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_LiveSubFps = uint.Parse(liveSubFps);
|
||||
}
|
||||
return _LiveSubFps;
|
||||
}
|
||||
set
|
||||
{
|
||||
_LiveSubFps = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_SUB_FPS, value.ToString());//生成保存本地
|
||||
LiveClassroom.ResetVideoSub();//重新设置副画面参数
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("LiveSubFps"));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 屏幕分享码率
|
||||
/// </summary>
|
||||
private uint _LiveSubBitrate = 2000;
|
||||
public uint LiveSubBitrate
|
||||
{
|
||||
get
|
||||
{
|
||||
var liveSubBitrate = storage.GetValue(INI_ROOT_KEY, INI_KEY_LIVE_SUB_BITTRATE);//本地缓存
|
||||
if (string.IsNullOrEmpty(liveSubBitrate))
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_SUB_BITTRATE, _LiveSubBitrate.ToString());//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_LiveSubBitrate = uint.Parse(liveSubBitrate);
|
||||
}
|
||||
return _LiveSubBitrate;
|
||||
}
|
||||
set
|
||||
{
|
||||
_LiveSubBitrate = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_SUB_BITTRATE, value.ToString());//生成保存本地
|
||||
LiveClassroom.ResetVideoSub();//重启音频
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("LiveSubBitrate"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 参数
|
||||
public TRTCVideoEncParam EncParams
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TRTCVideoEncParam { enableAdjustRes = true, resMode = TRTCVideoResolutionMode.TRTCVideoResolutionModeLandscape, videoBitrate = LiveMainBitrate, videoFps = LiveMainFps };
|
||||
}
|
||||
}
|
||||
public TRTCNetworkQosParam QosParams
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TRTCNetworkQosParam { preference = LiveMainLevel };
|
||||
}
|
||||
}
|
||||
public TRTCRenderParams RenderParams
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TRTCRenderParams { fillMode = TRTCVideoFillMode.TRTCVideoFillMode_Fill, mirrorType = TRTCVideoMirrorType.TRTCVideoMirrorType_Enable, rotation = TRTCVideoRotation.TRTCVideoRotation0 };
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// ini文件操作
|
||||
|
@ -254,6 +642,7 @@ namespace JianGongYun.TRTC.ViewModels
|
|||
private SettingWindowViewModel()
|
||||
{
|
||||
storage = new IniStorage(sPath);
|
||||
_ScreenRecordingDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonVideos);
|
||||
}
|
||||
|
||||
#region 配置持久化
|
||||
|
@ -261,44 +650,29 @@ namespace JianGongYun.TRTC.ViewModels
|
|||
//配置文件路径
|
||||
private string sPath = ".\\TRTCConfig.ini";
|
||||
//根节点
|
||||
public const string INI_ROOT_KEY = "TRTCLOCALCONFIG";
|
||||
// 设备
|
||||
public const string INI_KEY_CHOOSE_CAMERA = "INI_KEY_CHOOSE_CAMERA";//当前摄像头
|
||||
public const string INI_KEY_CHOOSE_MIC = "INI_KEY_CHOOSE_MIC";//当前麦克风
|
||||
// 音频
|
||||
public const string INI_KEY_AUDIO_MIC_VOLUME = "INI_KEY_AUDIO_MIC_VOLUME";//麦克风音量
|
||||
public const string INI_KEY_AUDIO_SPEAKER_VOLUME = "INI_KEY_AUDIO_SOURCE";//播放音量
|
||||
public const string INI_KEY_AUDIO_SOURCE = "INI_KEY_AUDIO_SOURCE";//音频来源
|
||||
public const string INI_KEY_AUDIO_SYSTEM_GATHER_VOLUME = "INI_KEY_AUDIO_SYSTEM_GATHER_VOLUME";//麦克风音量
|
||||
// 视频
|
||||
public const string INI_KEY_VIDEO_FPS = "INI_KEY_VIDEO_FPS";//视频FPS
|
||||
public const string INI_KEY_VIDEO_BITRATE = "INI_KEY_VIDEO_BITRATE";
|
||||
public const string INI_KEY_VIDEO_RESOLUTION = "INI_KEY_VIDEO_RESOLUTION";
|
||||
public const string INI_KEY_VIDEO_RES_MODE = "INI_KEY_VIDEO_RES_MODE";
|
||||
public const string INI_KEY_VIDEO_QUALITY = "INI_KEY_VIDEO_QUALITY";
|
||||
public const string INI_KEY_VIDEO_QUALITY_CONTROL = "INI_KEY_VIDEO_QUALITY_CONTROL";
|
||||
public const string INI_KEY_VIDEO_APP_SCENE = "INI_KEY_VIDEO_APP_SCENE";
|
||||
public const string INI_KEY_VIDEO_FILL_MODE = "INI_KEY_VIDEO_FILL_MODE";
|
||||
public const string INI_KEY_VIDEO_ROTATION = "INI_KEY_VIDEO_ROTATION";
|
||||
// 美颜
|
||||
public const string INI_KEY_BEAUTY_OPEN = "INI_KEY_BEAUTY_OPEN";
|
||||
public const string INI_KEY_BEAUTY_STYLE = "INI_KEY_BEAUTY_STYLE";
|
||||
public const string INI_KEY_BEAUTY_VALUE = "INI_KEY_BEAUTY_VALUE";
|
||||
public const string INI_KEY_WHITE_VALUE = "INI_KEY_WHITE_VALUE";
|
||||
public const string INI_KEY_RUDDINESS_VALUE = "INI_KEY_RUDDINESS_VALUE";
|
||||
// 大小流
|
||||
public const string INI_KEY_SET_PUSH_SMALLVIDEO = "INI_KEY_SET_PUSH_SMALLVIDEO";
|
||||
public const string INI_KEY_SET_PLAY_SMALLVIDEO = "INI_KEY_SET_PLAY_SMALLVIDEO";
|
||||
// 测试
|
||||
public const string INI_KEY_SET_NETENV_STYLE = "INI_KEY_SET_NETENV_STYLE";
|
||||
public const string INI_KEY_ROOMCALL_STYLE = "INI_KEY_ROOMCALL_STYLE";
|
||||
// 镜像
|
||||
public const string INI_KEY_LOCAL_VIDEO_MIRROR = "INI_KEY_LOCAL_VIDEO_MIRROR";
|
||||
public const string INI_KEY_REMOTE_VIDEO_MIRROR = "INI_KEY_REMOTE_VIDEO_MIRROR";
|
||||
// 音量提示
|
||||
public const string INI_KEY_SHOW_AUDIO_VOLUME = "INI_KEY_SHOW_AUDIO_VOLUME";
|
||||
// 混流
|
||||
public const string INI_KEY_CLOUD_MIX_TRANSCODING = "INI_KEY_CLOUD_MIX_TRANSCODING";
|
||||
private const string INI_ROOT_KEY = "TRTCLOCALCONFIG";
|
||||
//音频
|
||||
private const string INI_KEY_CHOOSE_MIC = "INI_KEY_CHOOSE_MIC";//当前麦克风
|
||||
private const string INI_KEY_AUDIO_MIC_VOLUME = "INI_KEY_AUDIO_MIC_VOLUME";//麦克风音量
|
||||
private const string INI_KEY_AUDIO_SPEAKER_VOLUME = "INI_KEY_AUDIO_SOURCE";//播放音量
|
||||
private const string INI_KEY_AUDIO_SOURCE = "INI_KEY_AUDIO_SOURCE";//音频来源
|
||||
private const string INI_KEY_AUDIO_SYSTEM_GATHER_VOLUME = "INI_KEY_AUDIO_SYSTEM_GATHER_VOLUME";//麦克风音量
|
||||
//录屏
|
||||
private const string INI_KEY_SCREEN_RECORDING_FPS = "INI_KEY_SCREEN_RECORDING_FPS";//视频帧率(fps)
|
||||
private const string INI_KEY_SCREEN_RECORDING_AUDIO_BITRATE = "INI_KEY_SCREEN_RECORDING_AUDIO_BITRATE";//音频码率
|
||||
private const string INI_KEY_SCREEN_RECORDING_AUDIO_FREQ = "INI_KEY_SCREEN_RECORDING_AUDIO_FREQ";//音频采样率
|
||||
private const string INI_KEY_SCREEN_RECORDING_PROFILE_LEVEL = "INI_KEY_SCREEN_RECORDING_PROFILE_LEVEL";//编码级别
|
||||
private const string INI_KEY_SCREEN_RECORDING_COUNTDOWN = "INI_KEY_SCREEN_RECORDING_COUNTDOWN";//录制倒计时
|
||||
private const string INI_KEY_SCREEN_RECORDING_DIR = "INI_KEY_SCREEN_RECORDING_DIR";//录制保存路径
|
||||
//直播
|
||||
private const string INI_KEY_LIVE_AUDIO_LEVEL = "INI_KEY_LIVE_AUDIO_LEVEL";//直播音频等级
|
||||
private const string INI_KEY_LIVE_MAIN_FPS = "INI_KEY_LIVE_MAIN_FPS";//直播主帧率
|
||||
private const string INI_KEY_LIVE_MAIN_BITTRATE = "INI_KEY_LIVE_MAIN_BITTRATE";//直播主码率
|
||||
private const string INI_KEY_LIVE_MAIN_LEVEL = "INI_KEY_LIVE_MAIN_LEVEL";//主画面级别
|
||||
private const string INI_KEY_LIVE_SUB_FPS = "INI_KEY_LIVE_SUB_FPS";//屏幕分享帧率
|
||||
private const string INI_KEY_LIVE_SUB_BITTRATE = "INI_KEY_LIVE_SUB_BITTRATE";//屏幕分享码率
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,14 @@
|
|||
Background="#232428">
|
||||
<!--窗口填满-->
|
||||
<Metro:MetroWindow.Resources>
|
||||
<Geometry x:Key="Icon_Browser">M512 884.363636c-50.059636 0-98.722909-9.890909-144.64-29.393454a372.922182 372.922182 0 0 1-118.365091-79.965091 372.922182 372.922182 0 0 1-79.965091-118.365091A367.872 367.872 0 0 1 139.636364 512c0-50.036364 9.890909-98.722909 29.393454-144.64a372.945455 372.945455 0 0 1 79.965091-118.365091 372.922182 372.922182 0 0 1 118.365091-79.965091A367.872 367.872 0 0 1 512 139.636364c50.059636 0 98.722909 9.890909 144.64 29.393454a372.945455 372.945455 0 0 1 118.365091 79.965091 372.922182 372.922182 0 0 1 79.965091 118.365091A367.872 367.872 0 0 1 884.363636 512c0 50.059636-9.890909 98.722909-29.393454 144.64a372.945455 372.945455 0 0 1-79.965091 118.365091 372.922182 372.922182 0 0 1-118.365091 79.965091A367.848727 367.848727 0 0 1 512 884.363636z m0-698.181818c-43.776 0-86.341818 8.634182-126.464 25.693091a326.516364 326.516364 0 0 0-103.633455 70.050909 326.516364 326.516364 0 0 0-70.027636 103.610182A321.629091 321.629091 0 0 0 186.181818 512c0 43.776 8.634182 86.341818 25.693091 126.464a326.516364 326.516364 0 0 0 70.050909 103.633455 326.516364 326.516364 0 0 0 103.610182 70.027636A321.652364 321.652364 0 0 0 512 837.818182c43.776 0 86.341818-8.657455 126.464-25.693091a326.516364 326.516364 0 0 0 103.633455-70.050909 326.516364 326.516364 0 0 0 70.027636-103.610182A321.652364 321.652364 0 0 0 837.818182 512c0-43.776-8.657455-86.341818-25.693091-126.464a326.516364 326.516364 0 0 0-70.050909-103.633455 326.516364 326.516364 0 0 0-103.610182-70.027636A321.652364 321.652364 0 0 0 512 186.181818z m-170.077091 512.162909a18.013091 18.013091 0 0 1-17.408-22.667636l70.865455-265.774546a18.013091 18.013091 0 0 1 12.753454-12.753454l265.774546-70.865455a18.013091 18.013091 0 0 1 22.039272 22.039273l-70.865454 265.774546a18.013091 18.013091 0 0 1-12.776727 12.753454L346.554182 697.716364a18.013091 18.013091 0 0 1-4.654546 0.628363z m85.573818-269.079272l-60.16 225.62909 225.605818-60.16 60.16-225.62909-225.605818 60.16z m111.755637 126.138181a17.966545 17.966545 0 0 1-12.730182-5.282909l-46.801455-46.778182a18.013091 18.013091 0 1 1 25.483637-25.506909l46.778181 46.801455a18.013091 18.013091 0 0 1-12.730181 30.766545z</Geometry>
|
||||
<Geometry x:Key="Icon_Setting">M372.134088 1004.846981a509.94041 509.94041 0 0 1-159.298198-76.821527l2.164315-103.514738a93.088793 93.088793 0 0 0-74.238313-93.088794l-101.536602-20.991523A509.428422 509.428422 0 0 1 0.011636 537.983409l82.243949-62.834935a93.088793 93.088793 0 0 0 26.507034-116.104998l-46.89348-92.390627A514.152678 514.152678 0 0 1 172.225904 128.415991l100.419536 25.133974a93.088793 93.088793 0 0 0 107.284834-51.664281l43.007023-94.252403a515.246472 515.246472 0 0 1 88.434354-7.610009c30.137497 0 59.669917 2.606486 88.411081 7.610009l43.007023 94.252403a93.088793 93.088793 0 0 0 107.284834 51.664281l100.396264-25.133974a514.152678 514.152678 0 0 1 110.356765 138.236858l-46.870208 92.390627a93.088793 93.088793 0 0 0 26.483762 116.104998l82.243949 62.834935a509.428422 509.428422 0 0 1-39.213654 172.44699l-101.51333 20.968251a93.088793 93.088793 0 0 0-74.238312 93.088793l2.141042 103.538011a509.94041 509.94041 0 0 1-159.298198 76.798255l-79.684007-66.279221a93.088793 93.088793 0 0 0-119.060567 0l-79.684007 66.302493zM511.348378 721.461421a209.449785 209.449785 0 1 0 0-418.89957 209.449785 209.449785 0 0 0 0 418.89957z</Geometry>
|
||||
<Geometry x:Key="Icon_Camera">M512 85.33312C323.499138 85.33312 170.66752 238.164738 170.66752 426.6656s152.831618 341.33248 341.33248 341.33248 341.33248-152.831618 341.33248-341.33248S700.500862 85.33312 512 85.33312zM85.3344 426.6656C85.3344 191.032411 276.366811 0 512 0c235.661633 0 426.6656 191.032411 426.6656 426.6656 0 235.661633-191.003967 426.6656-426.6656 426.6656-235.633189 0-426.6656-191.003967-426.6656-426.6656z m127.99968 554.66528A42.66656 42.66656 0 0 1 256.00064 938.66432h511.99872a42.66656 42.66656 0 1 1 0 85.33312H256.00064a42.66656 42.66656 0 0 1-42.66656-42.66656z M459.776131 775.166062a42.239894 42.239894 0 0 1 19.114618 56.888747l-85.560675 169.642242a42.951004 42.951004 0 0 1-56.774969 17.806178 42.239894 42.239894 0 0 1-19.71195-55.722527l85.560675-169.642243a42.951004 42.951004 0 0 1 57.372301-18.972397z m132.892112 0a42.239894 42.239894 0 0 0-19.114619 56.888747l85.560675 169.642242a42.951004 42.951004 0 0 0 56.774969 17.806178 42.239894 42.239894 0 0 0 19.711951-55.722527l-85.560675-169.642243a42.951004 42.951004 0 0 0-57.372301-18.972397zM526.222187 321.136975c-61.439846 0-111.2175 49.350988-111.2175 110.250391 0 60.927848 49.777653 110.278835 111.2175 110.278835s111.2175-49.350988 111.217499-110.278835c0-60.870959-49.777653-110.250391-111.217499-110.250391z m-196.806619 110.250391c0-107.747286 88.120669-195.099957 196.806619-195.099957 108.685951 0 196.806619 87.352671 196.806619 195.128401 0 107.747286-88.120669 195.099957-196.806619 195.099957-108.685951 0-196.806619-87.352671-196.806619-195.128401zM526.222187 28.444373c23.60883 0 42.780337 19.000841 42.780337 42.410561v63.630063c0 23.409719-19.143063 42.382116-42.780337 42.382116-23.60883 0-42.780337-18.972397-42.780338-42.382116V70.82649c0-23.409719 19.143063-42.410561 42.780338-42.410561z</Geometry>
|
||||
<Geometry x:Key="Icon_Screen">M864 159.872L160 160c-17.696 0-32 14.176-32 31.872v448a32 32 0 0 0 32 32h704a32 32 0 0 0 32-32v-448a32 32 0 0 0-32-32zM864 640H160V191.872h704V640z M928 32H96a96 96 0 0 0-96 96v640a95.904 95.904 0 0 0 95.68 95.936H416v38.944l-199.744 25.952A31.968 31.968 0 0 0 224 991.872h576a32 32 0 0 0 7.744-63.072L608 902.88v-38.944h320.32A95.904 95.904 0 0 0 1024 768V128a96 96 0 0 0-96-96z m32 736c0 17.632-14.368 32-32 32H96c-17.664 0-32-14.368-32-32V128a32 32 0 0 1 32-32h832c17.632 0 32 14.336 32 32v640z</Geometry>
|
||||
<Geometry x:Key="Icon_Mic">M486.4 972.8v-128.9728A332.8 332.8 0 0 1 179.2 512a25.6 25.6 0 0 1 51.2 0 281.6 281.6 0 0 0 563.2 0 25.6 25.6 0 1 1 51.2 0 332.8 332.8 0 0 1-307.2 331.8272V972.8h153.6a25.6 25.6 0 1 1 0 51.2h-358.4a25.6 25.6 0 1 1 0-51.2h153.6zM512 51.2a153.6 153.6 0 0 0-153.6 153.6v307.2a153.6 153.6 0 0 0 307.2 0V204.8a153.6 153.6 0 0 0-153.6-153.6z m0-51.2a204.8 204.8 0 0 1 204.8 204.8v307.2a204.8 204.8 0 1 1-409.6 0V204.8a204.8 204.8 0 0 1 204.8-204.8z</Geometry>
|
||||
<Geometry x:Key="Icon_User">M511.626 1.896C229.572 1.896 0.927 230.541 0.927 512.595c0 282.055 228.645 510.699 510.699 510.699s510.698-228.645 510.698-510.699S793.68 1.896 511.626 1.896z m0 69.641c243.606 0 441.058 197.474 441.058 441.058 0 87.347-25.392 168.762-69.194 237.271-73.419-77.609-170.944-132.204-280.597-151.829 70.004-33.755 118.404-105.164 118.404-188.066 0-115.388-93.535-208.922-208.923-208.922S303.452 294.583 303.452 409.97c0 82.902 48.399 154.311 118.403 188.066-110.093 19.704-207.96 74.661-281.479 152.77-44.177-68.704-69.808-150.465-69.808-238.211 0-243.584 197.496-441.058 441.058-441.058z</Geometry>
|
||||
<BooleanToVisibilityConverter x:Key="VisibilityOfBool" />
|
||||
<live:UnBooleanToVisibilityConverter x:Key="UnVisibilityOfBool" />
|
||||
<live:LiveTypeToBoolConverter x:Key="LiveTypeConverter"></live:LiveTypeToBoolConverter>
|
||||
</Metro:MetroWindow.Resources>
|
||||
<Canvas x:Name="Root" Background="Transparent">
|
||||
<!--父容器填满-->
|
||||
|
@ -34,6 +41,13 @@
|
|||
<TextBlock FontSize="14" Foreground="#3d7cf9" Text="{Binding StudentCount,Mode=OneWay}"></TextBlock>
|
||||
<TextBlock FontSize="14" Padding="3 0 0 0" Foreground="#bbbbbb" Text="人"></TextBlock>
|
||||
</StackPanel>
|
||||
<Metro:AduFlatButton Content="开始直播" Click="StartLive_Click" Tag="True" Canvas.Bottom="13" Canvas.Right="25" Visibility="{Binding IsLive, Converter={StaticResource UnVisibilityOfBool}}"></Metro:AduFlatButton>
|
||||
<Metro:AduFlatButton Content="结束直播" Click="StartLive_Click" Tag="False" Type="error" Canvas.Bottom="13" Canvas.Right="25" Visibility="{Binding IsLive, Converter={StaticResource VisibilityOfBool}}"></Metro:AduFlatButton>
|
||||
<StackPanel Visibility="{Binding IsLive, Converter={StaticResource VisibilityOfBool}}" Orientation="Horizontal" Canvas.Bottom="20" Canvas.Right="150">
|
||||
<Ellipse VerticalAlignment="Center" Width="10" Fill="LawnGreen" Height="10"></Ellipse>
|
||||
<TextBlock FontSize="15" Foreground="White" Margin="7 0 0 0">直播中</TextBlock>
|
||||
<TextBlock FontSize="15" Foreground="White" Margin="7 0 0 0" Text="{Binding LiveTimeCount}"></TextBlock>
|
||||
</StackPanel>
|
||||
</Canvas>
|
||||
<!--右方聊天学员面板-->
|
||||
<Canvas DockPanel.Dock="Right" Width="280" Background="#2f3035">
|
||||
|
@ -44,12 +58,108 @@
|
|||
<!--下方设置面板-->
|
||||
<Canvas DockPanel.Dock="Bottom" Height="70" Background="#232428">
|
||||
<!--设置按钮-->
|
||||
<Metro:AduSysButton Click="Setting_Btn_Click" Foreground="#fff" Canvas.Left="20" Canvas.Top="15" CornerRadius="6" Height="40" Width="40" Icon="{StaticResource Icon_Browser}" Content="" />
|
||||
<Button Click="Setting_Btn_Click" Style="{StaticResource CusIconBtn}" Canvas.Left="27" Canvas.Top="15" Background="Transparent" BorderThickness="0">
|
||||
<Button.Content>
|
||||
<StackPanel>
|
||||
<Path Width="18" Height="18" Fill="#fff" Shape.Stretch="Fill" Data="{StaticResource Icon_Setting}" />
|
||||
<TextBlock Foreground="#fff" Margin="0 3 0 0">设置</TextBlock>
|
||||
</StackPanel>
|
||||
</Button.Content>
|
||||
</Button>
|
||||
</Canvas>
|
||||
<!--中间面板-->
|
||||
<Canvas Background="#151618">
|
||||
|
||||
<Canvas x:Name="CusContent" Background="#151618">
|
||||
<!--直播前-->
|
||||
<Grid Canvas.Top="0" Canvas.Left="0" Height="{Binding ElementName=CusContent,Path=ActualHeight}" Width="{Binding ElementName=CusContent,Path=ActualWidth}" Visibility="{Binding IsLive, Converter={StaticResource UnVisibilityOfBool}}">
|
||||
<StackPanel Width="700" VerticalAlignment="Center">
|
||||
<TextBlock FontSize="30" Foreground="#999999" HorizontalAlignment="Center">请选择授课方式</TextBlock>
|
||||
<TextBlock HorizontalAlignment="Center" FontSize="16" Margin="0 10 0 0" Foreground="#999999">您可在上课期间随时调整授课方式</TextBlock>
|
||||
<Grid Margin="0 30 0 0" Height="300">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition></ColumnDefinition>
|
||||
<ColumnDefinition></ColumnDefinition>
|
||||
<ColumnDefinition></ColumnDefinition>
|
||||
<ColumnDefinition></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition></RowDefinition>
|
||||
<RowDefinition></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Margin="5" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2" Background="#2f3035">
|
||||
<Canvas x:Name="CameraPrew">
|
||||
<Grid Width="{Binding ElementName=CameraPrew,Path=ActualWidth}" Height="{Binding ElementName=CameraPrew,Path=ActualHeight}" Canvas.Top="0" Canvas.Left="0">
|
||||
<Path Margin="0 0 0 30" Width="111" Height="111" Fill="#cccccc" Shape.Stretch="Fill" Data="{StaticResource Icon_User}" />
|
||||
</Grid>
|
||||
<Grid x:Name="BeforeLiveViewWrap" Width="{Binding ElementName=CameraPrew,Path=ActualWidth}" Height="{Binding ElementName=CameraPrew,Path=ActualHeight}" Canvas.Top="0" Canvas.Left="0"></Grid>
|
||||
<TextBlock Width="{Binding ElementName=CameraPrew,Path=ActualWidth}" Canvas.Bottom="0" Canvas.Left="0" Padding="5" FontSize="14" Foreground="#cccccc" Background="#65888888" TextAlignment="Center">摄像头预览</TextBlock>
|
||||
</Canvas>
|
||||
</Grid>
|
||||
<Grid Margin="5" Background="#2f3035" Grid.Row="0" Grid.Column="2">
|
||||
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<StackPanel Margin="0 0 0 20" HorizontalAlignment="Center" Orientation="Horizontal">
|
||||
<Path Width="30" Height="35" Fill="#cccccc" Shape.Stretch="Fill" Data="{StaticResource Icon_Camera}" />
|
||||
<TextBlock FontSize="30" Margin="10 0" Foreground="#cccccc">+</TextBlock>
|
||||
<Path Width="30" Height="30" Fill="#cccccc" Shape.Stretch="Fill" Data="{StaticResource Icon_Screen}" />
|
||||
</StackPanel>
|
||||
<Metro:AduRadioButton x:Name="Rad1" Click="Tpye_Click" GroupName="LiveType" Foreground="#cccccc" Content="摄像头+屏幕分享" FontSize="14" IconWidth="16" IsChecked="{Binding LiveType,Converter={StaticResource LiveTypeConverter},ConverterParameter=CameraAndScreen}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Margin="5" Background="#2f3035" Grid.Row="0" Grid.Column="3">
|
||||
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Path Margin="0 0 0 30" Width="30" Height="30" Fill="#cccccc" Shape.Stretch="Fill" Data="{StaticResource Icon_Screen}" />
|
||||
<Metro:AduRadioButton x:Name="Rad2" Click="Tpye_Click" GroupName="LiveType" Foreground="#cccccc" Content="屏幕分享" FontSize="14" IconWidth="16" IsChecked="{Binding LiveType,Converter={StaticResource LiveTypeConverter},ConverterParameter=OnlyScreen}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Margin="5" Background="#2f3035" Grid.Row="1" Grid.Column="2">
|
||||
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Path Margin="0 0 0 25" Width="30" Height="35" Fill="#cccccc" Shape.Stretch="Fill" Data="{StaticResource Icon_Camera}" />
|
||||
<Metro:AduRadioButton x:Name="Rad3" Click="Tpye_Click" GroupName="LiveType" Foreground="#cccccc" Content="摄像头" FontSize="14" IconWidth="16" IsChecked="{Binding LiveType,Converter={StaticResource LiveTypeConverter},ConverterParameter=OnlyCamera}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Margin="5" Background="#2f3035" Grid.Row="1" Grid.Column="3">
|
||||
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Path Margin="0 0 0 15" Width="30" Height="45" Fill="#cccccc" Shape.Stretch="Fill" Data="{StaticResource Icon_Mic}" />
|
||||
<Metro:AduRadioButton x:Name="Rad4" Click="Tpye_Click" GroupName="LiveType" Foreground="#cccccc" Content="仅声音" FontSize="14" IconWidth="16" IsChecked="{Binding LiveType,Converter={StaticResource LiveTypeConverter},ConverterParameter=OnlyAudio}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<!--直播中-->
|
||||
<Grid Canvas.Top="0" Canvas.Left="0" Height="{Binding ElementName=CusContent,Path=ActualHeight}" Width="{Binding ElementName=CusContent,Path=ActualWidth}" Visibility="{Binding IsLive, Converter={StaticResource VisibilityOfBool}}">
|
||||
<TextBlock Foreground="White">true</TextBlock>
|
||||
</Grid>
|
||||
</Canvas>
|
||||
</DockPanel>
|
||||
<Grid x:Name="CountdownWrap" Visibility="Hidden" Canvas.Top="0" Canvas.Left="0" Background="Transparent" Panel.ZIndex="10" Height="{Binding ElementName=Root,Path=ActualHeight}" Width="{Binding ElementName=Root,Path=ActualWidth}"></Grid>
|
||||
|
||||
<Grid x:Name="ShareScreenListWrap" Visibility="Visible" Canvas.Top="0" Canvas.Left="0" Background="Transparent" Panel.ZIndex="5" Height="{Binding ElementName=Root,Path=ActualHeight}" Width="{Binding ElementName=Root,Path=ActualWidth}">
|
||||
<Border Width="970" Height="530" BorderBrush="#efefef" BorderThickness="2" CornerRadius="5">
|
||||
<Canvas x:Name="ScrollWrap" Width="970" Height="530" HorizontalAlignment="Center" VerticalAlignment="Center" Background="#f12f3035">
|
||||
<StackPanel Width="{Binding ElementName=ScrollWrap,Path=ActualWidth}">
|
||||
<TextBlock Foreground="White" FontSize="20" FontWeight="Bold" Padding="10" HorizontalAlignment="Center" VerticalAlignment="Center">请选择要分享的屏幕或窗口</TextBlock>
|
||||
</StackPanel>
|
||||
<ScrollViewer Canvas.Right="0" Canvas.Top="50" Height="480" Width="{Binding ElementName=ScrollWrap,Path=ActualWidth}">
|
||||
<WrapPanel>
|
||||
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
|
||||
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
|
||||
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
|
||||
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
|
||||
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
|
||||
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
|
||||
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
|
||||
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
|
||||
</WrapPanel>
|
||||
</ScrollViewer>
|
||||
<Button Click="Setting_Btn_Click" Style="{StaticResource CusIconBtn}" Canvas.Right="10" Canvas.Top="0" Background="Transparent" BorderThickness="0">
|
||||
<Button.Content>
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="30" Foreground="#fff" Margin="0 0 0 0">×</TextBlock>
|
||||
</StackPanel>
|
||||
</Button.Content>
|
||||
</Button>
|
||||
</Canvas>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Canvas>
|
||||
</Metro:MetroWindow>
|
||||
|
|
|
@ -12,6 +12,9 @@ using System.Windows.Media;
|
|||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using System.Linq;
|
||||
using System.Windows.Threading;
|
||||
using JianGongYun.TRTC.Components;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace JianGongYun.TRTC.Windows
|
||||
{
|
||||
|
@ -20,24 +23,38 @@ namespace JianGongYun.TRTC.Windows
|
|||
/// </summary>
|
||||
public partial class LiveWindow : MetroWindow
|
||||
{
|
||||
[DllImport("Kernel32.dll", EntryPoint = "AttachConsole", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern void AttachConsole(int dwProcessId);
|
||||
|
||||
ViewModels.LiveWindowViewModel LiveWindowViewModel;
|
||||
ViewModels.SettingWindowViewModel SettingWindowViewModel;
|
||||
public LiveWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
LiveWindowViewModel =new ViewModels.LiveWindowViewModel();
|
||||
InitializeComponent();
|
||||
AttachConsole(-1);
|
||||
LiveWindowViewModel = new ViewModels.LiveWindowViewModel();
|
||||
SettingWindowViewModel = ViewModels.SettingWindowViewModel.GetInstance();
|
||||
this.DataContext = LiveWindowViewModel;
|
||||
BorderBrush = new SolidColorBrush(color: Color.FromRgb(42, 43, 48));//窗口标题背景颜色
|
||||
|
||||
}
|
||||
private void aaaa(object sender, RoutedEventArgs e)
|
||||
|
||||
protected override void OnActivated(EventArgs e)
|
||||
{
|
||||
LiveWindowViewModel.StudentCount++;
|
||||
base.OnActivated(e);
|
||||
//颜色前台设置无效,手动调用才行
|
||||
var color = (SolidColorBrush)(new BrushConverter().ConvertFrom("#cccccc"));
|
||||
Rad1.Foreground = color;
|
||||
Rad2.Foreground = color;
|
||||
Rad3.Foreground = color;
|
||||
Rad4.Foreground = color;
|
||||
}
|
||||
|
||||
private Window settingWindow;
|
||||
//设置按钮
|
||||
private void Setting_Btn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var settingWindow = SettingWindow.GetInstance();
|
||||
settingWindow = SettingWindow.GetInstance();
|
||||
settingWindow.Closed += (a, b) => settingWindow = null;
|
||||
settingWindow.Show();
|
||||
if (settingWindow.WindowState != WindowState.Normal)
|
||||
{
|
||||
|
@ -45,5 +62,124 @@ namespace JianGongYun.TRTC.Windows
|
|||
}
|
||||
settingWindow.Topmost = true;
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
if (settingWindow != null)
|
||||
{
|
||||
settingWindow.Close();
|
||||
}
|
||||
base.OnClosed(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始/结束直播
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void StartLive_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var btn = sender as AduFlatButton;
|
||||
var start = Convert.ToBoolean(btn.Tag);
|
||||
if (start)//开始直播
|
||||
{
|
||||
this.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
btn.Type = AduSkin.Controls.FlatButtonSkinEnum.warning;
|
||||
btn.Content = "直播倒计时";
|
||||
}));
|
||||
StartCountdown(() =>
|
||||
{
|
||||
LiveWindowViewModel.IsLive = start;
|
||||
this.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
btn.Type = AduSkin.Controls.FlatButtonSkinEnum.info;
|
||||
btn.Content = "开始直播";
|
||||
}));
|
||||
}, SettingWindowViewModel.ScreenRecordingCountdown);
|
||||
}
|
||||
else
|
||||
{
|
||||
LiveWindowViewModel.IsLive = start;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始倒计时
|
||||
/// </summary>
|
||||
public void StartCountdown(Action countdownEnd, int time = 10)
|
||||
{
|
||||
CountdownEnd = countdownEnd;
|
||||
count = time;
|
||||
this.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
CountdownWrap.Visibility = Visibility.Visible;
|
||||
}));
|
||||
timer = new DispatcherTimer();
|
||||
timer.Interval = TimeSpan.FromSeconds(1);
|
||||
timer.Tick += new EventHandler(timer_Tick);
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 倒计时结束执行
|
||||
/// </summary>
|
||||
Action CountdownEnd;
|
||||
/// <summary>
|
||||
/// 倒计时时间
|
||||
/// </summary>
|
||||
private int count;
|
||||
/// <summary>
|
||||
/// 创建Timer对象
|
||||
/// </summary>
|
||||
private DispatcherTimer timer = null;
|
||||
private void timer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
timer.Stop();
|
||||
timer = null;
|
||||
this.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
CountdownWrap.Visibility = Visibility.Hidden;
|
||||
}));
|
||||
CountdownEnd?.Invoke();
|
||||
//count = 10;
|
||||
//timer.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
CountdownControl txt = new CountdownControl(this.CountdownWrap, this);
|
||||
txt.TxtValue = count.ToString();
|
||||
txt.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
|
||||
txt.VerticalAlignment = System.Windows.VerticalAlignment.Center;
|
||||
this.CountdownWrap.Children.Add(txt);
|
||||
count--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void Tpye_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
switch (LiveWindowViewModel.LiveType)
|
||||
{
|
||||
case Models.LiveTypeEnum.CameraAndScreen:
|
||||
break;
|
||||
case Models.LiveTypeEnum.OnlyScreen:
|
||||
|
||||
break;
|
||||
case Models.LiveTypeEnum.OnlyCamera:
|
||||
if (!LiveWindowViewModel.CameraRunning)
|
||||
{
|
||||
LiveClassroom.StartVideoMain(BeforeLiveViewWrap);
|
||||
}
|
||||
break;
|
||||
case Models.LiveTypeEnum.OnlyAudio:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,11 +50,125 @@
|
|||
</DockPanel>
|
||||
</StackPanel>
|
||||
</Metro:AduGroupBoxNor>
|
||||
<Metro:AduGroupBoxNor HeaderTemplate="{StaticResource CusHeaderTitle2}" Header="录屏设置" HeaderBackground="Transparent" BorderThickness="0" BorderBrush="{StaticResource DefaultBorderBrush}" FontSize="14" Height="380" HeaderPadding="10,6">
|
||||
|
||||
<Metro:AduGroupBoxNor HeaderTemplate="{StaticResource CusHeaderTitle2}" Header="录屏设置" HeaderBackground="Transparent" BorderThickness="0" BorderBrush="{StaticResource DefaultBorderBrush}" FontSize="14" HeaderPadding="10,6">
|
||||
<StackPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 视频帧率(fps)</TextBlock>
|
||||
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Content" SelectedValue="{Binding ScreenRecordingFps}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
|
||||
<ComboBoxItem Content="10" />
|
||||
<ComboBoxItem Content="12" />
|
||||
<ComboBoxItem Content="15" />
|
||||
<ComboBoxItem Content="20" />
|
||||
<ComboBoxItem Content="24" />
|
||||
<ComboBoxItem Content="25" />
|
||||
<ComboBoxItem Content="30" />
|
||||
</Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 音频码率</TextBlock>
|
||||
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding Path=ScreenRecordingAudioBitrate}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
|
||||
<ComboBoxItem Content="24Kbps" Tag="24000" />
|
||||
<ComboBoxItem Content="32Kbps" Tag="32000"/>
|
||||
<ComboBoxItem Content="64Kbps" Tag="64000"/>
|
||||
<ComboBoxItem Content="128Kbps" Tag="128000"/>
|
||||
<ComboBoxItem Content="192Kbps" Tag="192000"/>
|
||||
<ComboBoxItem Content="256Kbps" Tag="256000"/>
|
||||
<ComboBoxItem Content="320Kbps" Tag="320000"/>
|
||||
</Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 音频采样率</TextBlock>
|
||||
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding ScreenRecordingAudioFreq}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
|
||||
<ComboBoxItem Content="8000Hz" Tag="8000" />
|
||||
<ComboBoxItem Content="11025Hz" Tag="11025"/>
|
||||
<ComboBoxItem Content="16000Hz" Tag="16000"/>
|
||||
<ComboBoxItem Content="22050Hz" Tag="22050"/>
|
||||
<ComboBoxItem Content="37800Hz" Tag="37800"/>
|
||||
<ComboBoxItem Content="44100Hz" Tag="44100"/>
|
||||
<ComboBoxItem Content="48000Hz" Tag="48000"/>
|
||||
</Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 编码级别</TextBlock>
|
||||
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding ScreenRecordingProfileLevel}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
|
||||
<ComboBoxItem Content="基本画质" Tag="-profile:v baseline -level 3.0" />
|
||||
<ComboBoxItem Content="主流画质" Tag="-profile:v main -level 4.2"/>
|
||||
<ComboBoxItem Content="高级画质" Tag="-profile:v high -level 5.1"/>
|
||||
</Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 录制倒计时</TextBlock>
|
||||
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding ScreenRecordingCountdown}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
|
||||
<ComboBoxItem Content="3s" Tag="3" />
|
||||
<ComboBoxItem Content="5s" Tag="5"/>
|
||||
<ComboBoxItem Content="7s" Tag="7"/>
|
||||
<ComboBoxItem Content="10s" Tag="10"/>
|
||||
</Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 保存到文件夹</TextBlock>
|
||||
<Metro:AduFlatButton CornerRadius="0 3 3 0" Content="打开" x:Name="OpenDir" BorderBrush="#3399ff" BorderThickness="1" Click="OpenDir_Click" Width="50" DockPanel.Dock="Right" Margin="0 0 10 0" Type="info" />
|
||||
<Metro:AduFlatButton CornerRadius="3 0 0 3" Background="Transparent" BorderBrush="#3399ff" BorderThickness="1" Content="更改" x:Name="ChangeDir" Click="ChangeDir_Click" Width="50" DockPanel.Dock="Right" Margin=" 11 0 0 0" Type="info" />
|
||||
<Border BorderBrush="White" BorderThickness="1" CornerRadius="3">
|
||||
<TextBlock Cursor="IBeam" TextTrimming="CharacterEllipsis" ForceCursor="True" ToolTip="{Binding ScreenRecordingDir,Mode=OneWay}" Text="{Binding ScreenRecordingDir,Mode=OneWay}" Foreground="White" Padding="5 7"></TextBlock>
|
||||
</Border>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</Metro:AduGroupBoxNor>
|
||||
<Metro:AduGroupBoxNor HeaderTemplate="{StaticResource CusHeaderTitle3}" Header="直播设置" HeaderBackground="Transparent" BorderThickness="0" BorderBrush="{StaticResource DefaultBorderBrush}" FontSize="14" Height="380" HeaderPadding="10,6">
|
||||
|
||||
<Metro:AduGroupBoxNor HeaderTemplate="{StaticResource CusHeaderTitle3}" Header="直播设置" HeaderBackground="Transparent" BorderThickness="0" BorderBrush="{StaticResource DefaultBorderBrush}" FontSize="14" HeaderPadding="10,6">
|
||||
<StackPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 音频质量</TextBlock>
|
||||
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding LiveAudioLevel}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
|
||||
<ComboBoxItem Content="流畅" Tag="TRTCAudioQualitySpeech" />
|
||||
<ComboBoxItem Content="高" Tag="TRTCAudioQualityDefault"/>
|
||||
<ComboBoxItem Content="超高" Tag="TRTCAudioQualityMusic"/>
|
||||
</Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 摄像画面帧率(fps)</TextBlock>
|
||||
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Content" SelectedValue="{Binding LiveMainFps}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
|
||||
<ComboBoxItem Content="10" />
|
||||
<ComboBoxItem Content="12" />
|
||||
<ComboBoxItem Content="15" />
|
||||
<ComboBoxItem Content="20" />
|
||||
<ComboBoxItem Content="24" />
|
||||
</Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 摄像画面码率</TextBlock>
|
||||
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding Path=LiveMainBitrate}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
|
||||
<ComboBoxItem Content="1000Kbps" Tag="1000" />
|
||||
<ComboBoxItem Content="1200Kbps" Tag="1200"/>
|
||||
<ComboBoxItem Content="1600Kbps" Tag="1600"/>
|
||||
</Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 摄像画面级别</TextBlock>
|
||||
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding Path=LiveMainLevel}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
|
||||
<ComboBoxItem Content="弱网下保流畅" Tag="TRTCVideoQosPreferenceSmooth" />
|
||||
<ComboBoxItem Content="弱网下保清晰" Tag="TRTCVideoQosPreferenceClear"/>
|
||||
</Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 屏幕分享帧率(fps)</TextBlock>
|
||||
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Content" SelectedValue="{Binding LiveSubFps}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
|
||||
<ComboBoxItem Content="10" />
|
||||
<ComboBoxItem Content="12" />
|
||||
<ComboBoxItem Content="15" />
|
||||
<ComboBoxItem Content="20" />
|
||||
<ComboBoxItem Content="24" />
|
||||
</Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 屏幕分享码率</TextBlock>
|
||||
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding Path=LiveSubBitrate}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
|
||||
<ComboBoxItem Content="1200Kbps" Tag="1200"/>
|
||||
<ComboBoxItem Content="1600Kbps" Tag="1600"/>
|
||||
<ComboBoxItem Content="2000Kbps" Tag="2000"/>
|
||||
</Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</Metro:AduGroupBoxNor>
|
||||
</StackPanel>
|
||||
</Metro:MetroScrollViewer>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using AduSkin.Controls.Metro;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
@ -48,6 +49,10 @@ namespace JianGongYun.TRTC.Windows
|
|||
this.DataContext = mode;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 测试麦克风
|
||||
/// </summary>
|
||||
bool micTesting = false;
|
||||
private void TestMic(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
@ -87,5 +92,33 @@ namespace JianGongYun.TRTC.Windows
|
|||
Slider1.DecreaseColor = sliderColor;
|
||||
Slider2.DecreaseColor = sliderColor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开文件浏览器
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void OpenDir_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo { FileName = "explorer.exe", Arguments = mode.ScreenRecordingDir }
|
||||
};
|
||||
process.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改路径
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void ChangeDir_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
System.Windows.Forms.FolderBrowserDialog openFileDialog = new System.Windows.Forms.FolderBrowserDialog(); //选择文件夹
|
||||
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)//注意,此处一定要手动引入System.Window.Forms空间,否则你如果使用默认的DialogResult会发现没有OK属性
|
||||
{
|
||||
mode.ScreenRecordingDir = openFileDialog.SelectedPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue