设置窗口
This commit is contained in:
parent
4c0b1962fe
commit
de4c763f06
|
@ -12,6 +12,7 @@
|
|||
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/JianGongYun;component/Style/ShowControl.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/JianGongYun;component/Style/TRTCResource.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
<PackageReference Include="AduSkin" Version="1.1.1.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="zlib.net" Version="1.0.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' != 'net45'">
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.0" />
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:Metro="clr-namespace:AduSkin.Controls.Metro;assembly=AduSkin">
|
||||
<!--#region 设置窗口布局样式-->
|
||||
<SolidColorBrush x:Key="DefaultBorderBrush" Color="#424346" />
|
||||
<SolidColorBrush x:Key="ComboBoxBrush" Color="#6a6a6a"></SolidColorBrush>
|
||||
<SolidColorBrush x:Key="Item.SelectedActive.foreground" Color="#396cd2" />
|
||||
<SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da" />
|
||||
|
||||
<Style x:Key="LeftIndicatorStyle" TargetType="{x:Type Metro:SegmentControl}">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="CornerRadius" Value="0" />
|
||||
<Setter Property="VerticalAlignment" Value="Top" />
|
||||
<Setter Property="BorderThickness" Value="0,0,0,0" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="Background" Value="#2a2b30" />
|
||||
<Setter Property="Foreground" Value="#ffffff" />
|
||||
<Setter Property="ItemsPanel">
|
||||
<Setter.Value>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical" IsItemsHost="True" />
|
||||
</ItemsPanelTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="LeftIndicatorItemStyle" TargetType="{x:Type Metro:SegmentItem}">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Right" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Metro:SegmentItem}">
|
||||
<Border x:Name="Bd"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
SnapsToDevicePixels="true" UseLayoutRounding="True">
|
||||
<ContentPresenter Margin="20,8,20,8"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<!--<Setter TargetName="Bd" Property="Background" Value="{StaticResource Item.MouseOver.Background}" />-->
|
||||
<Setter TargetName="Bd" Property="BorderBrush" Value="{StaticResource Item.MouseOver.Border}" />
|
||||
</Trigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsMouseOver" Value="True" />
|
||||
<Condition Property="IsSelected" Value="True" />
|
||||
</MultiTrigger.Conditions>
|
||||
<!--<Setter TargetName="Bd" Property="Background" Value="{StaticResource Item.MouseOver.Background}" />-->
|
||||
<Setter TargetName="Bd" Property="BorderBrush" Value="{StaticResource Item.MouseOver.Border}" />
|
||||
</MultiTrigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="Selector.IsSelectionActive" Value="False" />
|
||||
<Condition Property="IsSelected" Value="True" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter TargetName="Bd" Property="Background" Value="#232428" />
|
||||
<Setter Property="Foreground" Value="{StaticResource Item.SelectedActive.foreground}" />
|
||||
</MultiTrigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="Selector.IsSelectionActive" Value="True" />
|
||||
<Condition Property="IsSelected" Value="True" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter TargetName="Bd" Property="Background" Value="#232428" />
|
||||
<Setter Property="Foreground" Value="{StaticResource Item.SelectedActive.foreground}" />
|
||||
</MultiTrigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="Bd" Property="TextElement.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<!--#endregion-->
|
||||
|
||||
<!--设置窗口属性行样式-->
|
||||
<Style TargetType="DockPanel" x:Key="SettingItem">
|
||||
<Setter Property="Height" Value="35"></Setter>
|
||||
<Setter Property="Margin" Value="10"></Setter>
|
||||
<Setter Property="VerticalAlignment" Value="Top"></Setter>
|
||||
</Style>
|
||||
<!--设置窗口属性行标题-->
|
||||
<Style TargetType="TextBlock" x:Key="SettingItemText">
|
||||
<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="TextAlignment" Value="Left"></Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
|
@ -0,0 +1,10 @@
|
|||
<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>
|
|
@ -0,0 +1,26 @@
|
|||
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,127 @@
|
|||
using JianGongYun.TRTC.Models;
|
||||
using JianGongYun.TRTC.Utils;
|
||||
using JianGongYun.TRTC.Windows;
|
||||
using ManageLiteAV;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace JianGongYun.TRTC
|
||||
{
|
||||
/// <summary>
|
||||
/// 直播调用对象全放这里
|
||||
/// </summary>
|
||||
public static class LiveClassroom
|
||||
{
|
||||
const uint SDKAppID = 1400463444;
|
||||
const string SDKAppKEY = "6ee2586282eb8ab5bff3f917b44500c4ffd9bbd3d820258b1fa8cdd470cfd1ee";
|
||||
/// <summary>
|
||||
/// TRTC实例
|
||||
/// </summary>
|
||||
public static ITRTCCloud lTRTCCloud;
|
||||
/// <summary>
|
||||
/// 设备管理器
|
||||
/// </summary>
|
||||
public static ITXDeviceManager lTXDeviceManager;
|
||||
/// <summary>
|
||||
/// live窗口的调用窗口
|
||||
/// </summary>
|
||||
public static Window CallerWindow { get; private set; }
|
||||
/// <summary>
|
||||
/// 直播窗口
|
||||
/// </summary>
|
||||
public static Window CurrentLiveWindow;
|
||||
public static ClassroomEntity CurrentClassroomEntity { get; private set; }
|
||||
//public static int UserCount = 999;
|
||||
/// <summary>
|
||||
/// 进入直播教室
|
||||
/// </summary>
|
||||
/// <param name="callerWindow">调用窗口</param>
|
||||
/// <param name="classroomEntity">教室数据</param>
|
||||
public static void EnterTheClassroom(Window callerWindow, ClassroomEntity classroomEntity)
|
||||
{
|
||||
if (CurrentLiveWindow != null)
|
||||
{
|
||||
_ = AduSkin.Controls.Metro.AduMessageBox.Show("已经进入教室", "提醒");
|
||||
CurrentLiveWindow.Topmost = true;
|
||||
return;
|
||||
}
|
||||
CallerWindow = callerWindow;
|
||||
CurrentClassroomEntity = classroomEntity;
|
||||
CurrentLiveWindow = new LiveWindow();
|
||||
CurrentLiveWindow.Closed += CurrentLiveWindow_Closed;
|
||||
|
||||
|
||||
lTRTCCloud = ITRTCCloud.getTRTCShareInstance();//创建TRTC实例
|
||||
var roomPars = new TRTCParams
|
||||
{
|
||||
sdkAppId = SDKAppID,
|
||||
userId = CurrentClassroomEntity.TeacherId,
|
||||
userSig = GenTestUserSig(CurrentClassroomEntity.TeacherId),
|
||||
roomId = 0,//使用strRoomId
|
||||
strRoomId = CurrentClassroomEntity.TeacherId,
|
||||
role = TRTCRoleType.TRTCRoleAnchor
|
||||
};
|
||||
lTRTCCloud.enterRoom(ref roomPars, TRTCAppScene.TRTCAppSceneLIVE);//创建房间
|
||||
|
||||
//设备
|
||||
var settingViewMode = ViewModels.SettingWindowViewModel.GetInstance();
|
||||
lTXDeviceManager = lTRTCCloud.getDeviceManager();
|
||||
var currentMic = settingViewMode.CurrentMic;//麦克风
|
||||
if (!string.IsNullOrEmpty(currentMic))
|
||||
{
|
||||
var res = lTXDeviceManager.setCurrentDevice(TRTCDeviceType.TXMediaDeviceTypeMic, currentMic);
|
||||
Console.WriteLine($"设置麦克风:{res}");
|
||||
}
|
||||
//设备完结
|
||||
|
||||
|
||||
callerWindow.Hide();//隐藏调用窗口
|
||||
CurrentLiveWindow.Show();
|
||||
}
|
||||
|
||||
private static void CurrentLiveWindow_Closed(object sender, EventArgs e)
|
||||
{
|
||||
CurrentLiveWindow = null;
|
||||
CurrentClassroomEntity = null;
|
||||
CallerWindow.Show();//还原调用者窗口
|
||||
|
||||
lTXDeviceManager.Dispose();
|
||||
lTXDeviceManager = null;
|
||||
lTRTCCloud.exitRoom();
|
||||
ITRTCCloud.destroyTRTCShareInstance();//销毁TRTC实例
|
||||
lTRTCCloud.Dispose();
|
||||
lTRTCCloud = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 计算 UserSig 签名
|
||||
///
|
||||
/// 函数内部使用 HMAC-SHA256 非对称加密算法,对 SDKAPPID、userId 和 EXPIRETIME 进行加密
|
||||
///
|
||||
/// 该方案仅适合本地跑通demo和功能调试,产品真正上线发布,要使用服务器获取方案避免私钥被破解。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:
|
||||
///
|
||||
/// 本文件中的代码虽然能够正确计算出 UserSig,但仅适合快速调通 SDK 的基本功能,不适合线上产品,
|
||||
/// 这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。
|
||||
/// 一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。
|
||||
///
|
||||
/// 正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。
|
||||
/// 由于破解服务器的成本要高于破解客户端 App,所以服务器计算的方案能够更好地保护您的加密密钥。
|
||||
///
|
||||
/// 文档:https://cloud.tencent.com/document/product/647/17275#GetFromServer
|
||||
/// </remarks>
|
||||
public static string GenTestUserSig(string userId)
|
||||
{
|
||||
if (SDKAppID == 0 || string.IsNullOrEmpty(SDKAppKEY)) return null;
|
||||
TLSSigAPIv2 api = new TLSSigAPIv2((int)SDKAppID, SDKAppKEY);
|
||||
// 统一转换为UTF8,SDK内部是用UTF8编码。
|
||||
return api.GenSig(Util.UTF16To8(userId));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace JianGongYun.TRTC.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 教室实体数据
|
||||
/// </summary>
|
||||
public class ClassroomEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 教师id(长度不超过32字符,教师id同时视为直播教室id)
|
||||
/// </summary>
|
||||
public string TeacherId { get; set; }
|
||||
/// <summary>
|
||||
/// 教师名称
|
||||
/// </summary>
|
||||
public string TeacherName { get; set; }
|
||||
/// <summary>
|
||||
/// 课程名称
|
||||
/// </summary>
|
||||
public string ClassHead { get; set; }
|
||||
/// <summary>
|
||||
/// 章节名称
|
||||
/// </summary>
|
||||
public string ClassSubHead { get; set; }
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace JianGongYun.TRTC.Models
|
||||
{
|
||||
public class ComboBoxEntity
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Text { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace JianGongYun.TRTC.Utils
|
||||
{
|
||||
public class IniStorage
|
||||
{ // 声明INI文件的写操作函数
|
||||
[DllImport("kernel32")]
|
||||
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
|
||||
|
||||
// 声明INI文件的读操作函数
|
||||
[DllImport("kernel32")]
|
||||
private static extern int GetPrivateProfileString(string section, string key, string def, System.Text.StringBuilder retVal, int size, string filePath);
|
||||
|
||||
private string sPath = null;
|
||||
|
||||
public IniStorage(string path)
|
||||
{
|
||||
this.sPath = path;
|
||||
}
|
||||
|
||||
public void SetValue(string section, string key, string value)
|
||||
{
|
||||
// section=配置节,key=键名,value=键值,path=路径
|
||||
WritePrivateProfileString(section, key, value, sPath);
|
||||
}
|
||||
|
||||
public string GetValue(string section, string key)
|
||||
{
|
||||
// 每次从ini中读取多少字节
|
||||
System.Text.StringBuilder temp = new System.Text.StringBuilder(255);
|
||||
// section=配置节,key=键名,temp=上面,path=路径
|
||||
GetPrivateProfileString(section, key, "", temp, 255, sPath);
|
||||
return temp.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using zlib;
|
||||
|
||||
namespace JianGongYun.TRTC.Utils
|
||||
{
|
||||
public class TLSSigAPIv2
|
||||
{
|
||||
private readonly int sdkappid;
|
||||
private readonly string key;
|
||||
|
||||
public TLSSigAPIv2(int sdkappid, string key)
|
||||
{
|
||||
this.sdkappid = sdkappid;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
private static byte[] CompressBytes(byte[] sourceByte)
|
||||
{
|
||||
MemoryStream inputStream = new MemoryStream(sourceByte);
|
||||
Stream outStream = CompressStream(inputStream);
|
||||
byte[] outPutByteArray = new byte[outStream.Length];
|
||||
outStream.Position = 0;
|
||||
outStream.Read(outPutByteArray, 0, outPutByteArray.Length);
|
||||
return outPutByteArray;
|
||||
}
|
||||
|
||||
private static Stream CompressStream(Stream sourceStream)
|
||||
{
|
||||
MemoryStream streamOut = new MemoryStream();
|
||||
ZOutputStream streamZOut = new ZOutputStream(streamOut, zlibConst.Z_DEFAULT_COMPRESSION);
|
||||
CopyStream(sourceStream, streamZOut);
|
||||
streamZOut.finish();
|
||||
return streamOut;
|
||||
}
|
||||
|
||||
public static void CopyStream(System.IO.Stream input, System.IO.Stream output)
|
||||
{
|
||||
byte[] buffer = new byte[2000];
|
||||
int len;
|
||||
while ((len = input.Read(buffer, 0, 2000)) > 0)
|
||||
{
|
||||
output.Write(buffer, 0, len);
|
||||
}
|
||||
output.Flush();
|
||||
}
|
||||
|
||||
private string HMACSHA256(string identifier, long currTime, int expire, string base64UserBuf, bool userBufEnabled)
|
||||
{
|
||||
string rawContentToBeSigned = "TLS.identifier:" + identifier + "\n"
|
||||
+ "TLS.sdkappid:" + sdkappid + "\n"
|
||||
+ "TLS.time:" + currTime + "\n"
|
||||
+ "TLS.expire:" + expire + "\n";
|
||||
if (true == userBufEnabled)
|
||||
{
|
||||
rawContentToBeSigned += "TLS.userbuf:" + base64UserBuf + "\n";
|
||||
}
|
||||
using (HMACSHA256 hmac = new HMACSHA256())
|
||||
{
|
||||
UTF8Encoding encoding = new UTF8Encoding();
|
||||
Byte[] textBytes = encoding.GetBytes(rawContentToBeSigned);
|
||||
Byte[] keyBytes = encoding.GetBytes(key);
|
||||
Byte[] hashBytes;
|
||||
using (HMACSHA256 hash = new HMACSHA256(keyBytes))
|
||||
hashBytes = hash.ComputeHash(textBytes);
|
||||
return Convert.ToBase64String(hashBytes);
|
||||
}
|
||||
}
|
||||
|
||||
private string GenSig(string identifier, int expire, byte[] userbuf, bool userBufEnabled)
|
||||
{
|
||||
DateTime epoch = new DateTime(1970, 1, 1); // unix 时间戳
|
||||
Int64 currTime = (Int64)(DateTime.UtcNow - epoch).TotalMilliseconds / 1000;
|
||||
|
||||
string base64UserBuf;
|
||||
string jsonData;
|
||||
if (true == userBufEnabled)
|
||||
{
|
||||
base64UserBuf = Convert.ToBase64String(userbuf);
|
||||
string base64sig = HMACSHA256(identifier, currTime, expire, base64UserBuf, userBufEnabled);
|
||||
var jsonObj = new JObject();
|
||||
jsonObj["TLS.ver"] = "2.0";
|
||||
jsonObj["TLS.identifier"] = identifier;
|
||||
jsonObj["TLS.sdkappid"] = sdkappid;
|
||||
jsonObj["TLS.expire"] = expire;
|
||||
jsonObj["TLS.time"] = currTime;
|
||||
jsonObj["TLS.sig"] = base64sig;
|
||||
jsonObj["TLS.userbuf"] = base64UserBuf;
|
||||
jsonData = JsonConvert.SerializeObject(jsonObj);
|
||||
}
|
||||
else
|
||||
{
|
||||
string base64sig = HMACSHA256(identifier, currTime, expire, "", false);
|
||||
var jsonObj = new JObject();
|
||||
jsonObj["TLS.ver"] = "2.0";
|
||||
jsonObj["TLS.identifier"] = identifier;
|
||||
jsonObj["TLS.sdkappid"] = sdkappid;
|
||||
jsonObj["TLS.expire"] = expire;
|
||||
jsonObj["TLS.time"] = currTime;
|
||||
jsonObj["TLS.sig"] = base64sig;
|
||||
jsonData = JsonConvert.SerializeObject(jsonObj);
|
||||
}
|
||||
byte[] buffer = Encoding.UTF8.GetBytes(jsonData);
|
||||
return Convert.ToBase64String(CompressBytes(buffer))
|
||||
.Replace('+', '*').Replace('/', '-').Replace('=', '_');
|
||||
}
|
||||
|
||||
public string GenSig(string identifier, int expire = 180 * 86400)
|
||||
{
|
||||
return GenSig(identifier, expire, null, false);
|
||||
}
|
||||
|
||||
public string GenSigWithUserBuf(string identifier, int expire, byte[] userbuf)
|
||||
{
|
||||
return GenSig(identifier, expire, userbuf, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace JianGongYun.TRTC.Utils
|
||||
{
|
||||
public class Util
|
||||
{
|
||||
public static string UTF16To8(string str)
|
||||
{
|
||||
byte[] utf16Bytes = Encoding.Unicode.GetBytes(str);
|
||||
byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes);
|
||||
return Encoding.UTF8.GetString(utf8Bytes);
|
||||
}
|
||||
|
||||
public static bool IsSys64bit()
|
||||
{
|
||||
return IntPtr.Size == 8;
|
||||
}
|
||||
|
||||
public static string GetRandomString(int iLength)
|
||||
{
|
||||
string buffer = "0123456789";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Random r = new Random(iLength);
|
||||
int range = buffer.Length;
|
||||
for (int i = 0; i < iLength; i++)
|
||||
{
|
||||
sb.Append(buffer.Substring(r.Next(range), 1));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string MD5(string str)
|
||||
{
|
||||
MD5 md5 = System.Security.Cryptography.MD5.Create();
|
||||
byte[] byteOld = Encoding.UTF8.GetBytes(str);
|
||||
byte[] byteNew = md5.ComputeHash(byteOld);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (byte b in byteNew)
|
||||
{
|
||||
// 将字节转换成16进制表示的字符串
|
||||
sb.Append(b.ToString("x2"));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static bool IsTestEnv()
|
||||
{
|
||||
string path = Environment.CurrentDirectory + "\\ShowTestEnv.txt";
|
||||
return File.Exists(path);
|
||||
}
|
||||
|
||||
public static string ConvertMSToTime(int lCurMS, int lDurationMS)
|
||||
{
|
||||
string strTime = "00:00/00:00";
|
||||
|
||||
int nTotalDurationSecond = lDurationMS / 1000;
|
||||
int nDurationMinute = nTotalDurationSecond / 60;
|
||||
int nDurationSecond = nTotalDurationSecond % 60;
|
||||
|
||||
int nTotalCurSecond = lCurMS / 1000;
|
||||
int nCurMinute = nTotalCurSecond / 60;
|
||||
int nCurSecond = nTotalCurSecond % 60;
|
||||
|
||||
string format = "{0:00}:{1:00}/{2:00}:{3:00}";
|
||||
|
||||
strTime = string.Format(format, nCurMinute, nCurSecond, nDurationMinute, nDurationSecond);
|
||||
|
||||
return strTime;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
|
||||
namespace JianGongYun.TRTC.ViewModels
|
||||
{
|
||||
public class LiveWindowViewModel : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 教室信息
|
||||
/// </summary>
|
||||
public Models.ClassroomEntity ClassroomEntity { get { return LiveClassroom.CurrentClassroomEntity; } }
|
||||
|
||||
/// <summary>
|
||||
/// 学生总数
|
||||
/// </summary>
|
||||
private int _StudentCount = 0;
|
||||
public int StudentCount
|
||||
{
|
||||
set
|
||||
{
|
||||
_StudentCount = value;
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("StudentCount"));//对StudentCount进行监听
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return _StudentCount;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否在直播中
|
||||
/// </summary>
|
||||
private bool _IsLive = false;
|
||||
public bool IsLive
|
||||
{
|
||||
set
|
||||
{
|
||||
_IsLive = value;
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("IsLive"));
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return _IsLive;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,304 @@
|
|||
using JianGongYun.TRTC.Models;
|
||||
using JianGongYun.TRTC.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
using JianGongYun.TRTC.Components;
|
||||
using System.Windows;
|
||||
|
||||
namespace JianGongYun.TRTC.ViewModels
|
||||
{
|
||||
public class SettingWindowViewModel : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
/// <summary>
|
||||
/// 单例
|
||||
/// </summary>
|
||||
private static SettingWindowViewModel _Instance;
|
||||
|
||||
public static SettingWindowViewModel GetInstance()
|
||||
{
|
||||
if (_Instance == null)
|
||||
{
|
||||
_Instance = new SettingWindowViewModel();
|
||||
}
|
||||
return _Instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 直播主窗口viewmodel
|
||||
/// </summary>
|
||||
private LiveWindowViewModel LiveWindowViewModel
|
||||
{
|
||||
get
|
||||
{
|
||||
return LiveClassroom.CurrentLiveWindow.DataContext == null ? null : LiveClassroom.CurrentLiveWindow.DataContext as LiveWindowViewModel;
|
||||
}
|
||||
}
|
||||
|
||||
#region 麦克风
|
||||
/// <summary>
|
||||
/// 集合,实时获取
|
||||
/// </summary>
|
||||
public List<ComboBoxEntity> MicList
|
||||
{
|
||||
get
|
||||
{
|
||||
var mics = LiveClassroom.lTXDeviceManager.getDevicesList(ManageLiteAV.TRTCDeviceType.TXMediaDeviceTypeMic);
|
||||
List<ComboBoxEntity> micList = new List<ComboBoxEntity>();
|
||||
var count = mics.getCount();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
var temp = new ComboBoxEntity { Id = mics.getDevicePID(i), Text = mics.getDeviceName(i) };
|
||||
micList.Add(temp);
|
||||
}
|
||||
return micList;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前
|
||||
/// </summary>
|
||||
private string _CurrentMic;
|
||||
public string CurrentMic
|
||||
{
|
||||
get
|
||||
{
|
||||
var tempList = this.MicList;
|
||||
if (tempList.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (string.IsNullOrEmpty(_CurrentMic) || !tempList.Any(a => a.Id == _CurrentMic))//第一次取或者设备发生变动找不到上次的选择
|
||||
{
|
||||
var localMic = storage.GetValue(INI_ROOT_KEY, INI_KEY_CHOOSE_MIC);//本地缓存
|
||||
if (string.IsNullOrEmpty(localMic))//本地没有就取第一个
|
||||
{
|
||||
_CurrentMic = tempList.First().Id;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_CHOOSE_MIC, _CurrentMic);//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_CurrentMic = localMic;
|
||||
var temp = tempList.Where(a => a.Id == localMic).FirstOrDefault();
|
||||
if (temp == null)//找不到上次缓存的设备就取第一个
|
||||
{
|
||||
_CurrentMic = tempList.First().Id;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_CHOOSE_MIC, _CurrentMic);//生成初始数据
|
||||
}
|
||||
}
|
||||
}
|
||||
return _CurrentMic;
|
||||
}
|
||||
set
|
||||
{
|
||||
_CurrentMic = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_CHOOSE_MIC, value);//生成保存本地
|
||||
LiveClassroom.lTXDeviceManager.setCurrentDevice(ManageLiteAV.TRTCDeviceType.TXMediaDeviceTypeMic, _CurrentMic);//设置麦克
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("CurrentMic"));//对CurrentMic进行监听
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 麦克风采集音量
|
||||
/// </summary>
|
||||
private uint _MicVolume = 100;
|
||||
public uint MicVolume
|
||||
{
|
||||
get
|
||||
{
|
||||
var micVolume = storage.GetValue(INI_ROOT_KEY, INI_KEY_AUDIO_MIC_VOLUME);//本地缓存
|
||||
if (string.IsNullOrEmpty(micVolume))//本地没有就取第一个
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_AUDIO_MIC_VOLUME, _MicVolume.ToString());//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_MicVolume = uint.Parse(micVolume);
|
||||
}
|
||||
return _MicVolume;
|
||||
}
|
||||
set
|
||||
{
|
||||
_MicVolume = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_AUDIO_MIC_VOLUME, value.ToString());//生成保存本地
|
||||
var res = LiveClassroom.lTXDeviceManager.setCurrentDeviceVolume(ManageLiteAV.TRTCDeviceType.TXMediaDeviceTypeMic, _MicVolume);//设置麦克音量
|
||||
Console.WriteLine("设置麦克风采集音量" + res);
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("MicVolume"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 音频来源
|
||||
|
||||
/// <summary>
|
||||
/// 音频来源
|
||||
/// </summary>
|
||||
private string _AudioSource = "1";
|
||||
public string AudioSource
|
||||
{
|
||||
get
|
||||
{
|
||||
var audioSource = storage.GetValue(INI_ROOT_KEY, INI_KEY_AUDIO_SOURCE);//本地缓存
|
||||
if (string.IsNullOrEmpty(audioSource))//本地没有就取第一个
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_AUDIO_SOURCE, _AudioSource);//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_AudioSource = audioSource;
|
||||
}
|
||||
return _AudioSource;
|
||||
}
|
||||
set
|
||||
{
|
||||
_AudioSource = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_AUDIO_SOURCE, value);//生成保存本地
|
||||
if (_AudioSource == "1")//只采集麦克风,关闭系统音采集
|
||||
{
|
||||
ShowSytemGatherSlider = Visibility.Hidden;
|
||||
LiveClassroom.lTRTCCloud.stopSystemAudioLoopback();
|
||||
}
|
||||
else if (_AudioSource == "2")//麦和系统音,开启采集系统音
|
||||
{
|
||||
ShowSytemGatherSlider = Visibility.Visible;
|
||||
LiveClassroom.lTRTCCloud.startSystemAudioLoopback(null);
|
||||
}
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("AudioSource"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否显示系统采集滑动条
|
||||
/// </summary>
|
||||
private Visibility _ShowSytemGatherSlider = Visibility.Hidden;
|
||||
public Visibility ShowSytemGatherSlider
|
||||
{
|
||||
get
|
||||
{
|
||||
if (AudioSource=="2")
|
||||
{
|
||||
_ShowSytemGatherSlider = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ShowSytemGatherSlider = Visibility.Hidden;
|
||||
}
|
||||
return _ShowSytemGatherSlider;
|
||||
}
|
||||
set
|
||||
{
|
||||
_ShowSytemGatherSlider = value;
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("ShowSytemGatherSlider"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 系统采集音量
|
||||
/// </summary>
|
||||
private uint _SytemGatherVolume = 100;
|
||||
public uint SytemGatherVolume
|
||||
{
|
||||
get
|
||||
{
|
||||
var sytemGatherVolume = storage.GetValue(INI_ROOT_KEY, INI_KEY_AUDIO_SYSTEM_GATHER_VOLUME);//本地缓存
|
||||
if (string.IsNullOrEmpty(sytemGatherVolume))//本地没有就取第一个
|
||||
{
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_AUDIO_SYSTEM_GATHER_VOLUME, _SytemGatherVolume.ToString());//生成初始数据
|
||||
}
|
||||
else
|
||||
{
|
||||
_SytemGatherVolume = uint.Parse(sytemGatherVolume);
|
||||
}
|
||||
return _SytemGatherVolume;
|
||||
}
|
||||
set
|
||||
{
|
||||
_SytemGatherVolume = value;
|
||||
storage.SetValue(INI_ROOT_KEY, INI_KEY_AUDIO_SYSTEM_GATHER_VOLUME, value.ToString());//生成保存本地
|
||||
LiveClassroom.lTRTCCloud.setSystemAudioLoopbackVolume(_SytemGatherVolume);//设置系统采集音量
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("SytemGatherVolume"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// ini文件操作
|
||||
/// </summary>
|
||||
private IniStorage storage;
|
||||
private SettingWindowViewModel()
|
||||
{
|
||||
storage = new IniStorage(sPath);
|
||||
}
|
||||
|
||||
#region 配置持久化
|
||||
|
||||
//配置文件路径
|
||||
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";
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
<Metro:MetroWindow x:Class="JianGongYun.TRTC.Windows.LiveWindow"
|
||||
xmlns:Metro="clr-namespace:AduSkin.Controls.Metro;assembly=AduSkin"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:JianGongYun.TRTC.Windows"
|
||||
xmlns:live="clr-namespace:JianGongYun.TRTC"
|
||||
mc:Ignorable="d"
|
||||
Title="建工云课堂" MinWidth="600" MinHeight="350"
|
||||
d:DesignHeight="1200" d:DesignWidth="1600"
|
||||
BorderThickness="0" WindowStyle="None"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
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>
|
||||
</Metro:MetroWindow.Resources>
|
||||
<Canvas x:Name="Root" Background="Transparent">
|
||||
<!--父容器填满-->
|
||||
<DockPanel Panel.ZIndex="0" Height="{Binding ElementName=Root,Path=ActualHeight}" Width="{Binding ElementName=Root,Path=ActualWidth}">
|
||||
<!--上方标题面板-->
|
||||
<Canvas DockPanel.Dock="Top" Height="60" Background="#232428">
|
||||
<StackPanel Height="30">
|
||||
<TextBlock VerticalAlignment="Center" FontSize="16" Padding="20 6" Foreground="White">
|
||||
<Bold>
|
||||
《<Run Text="{Binding ClassroomEntity.ClassHead,Mode=OneTime}"></Run>》
|
||||
</Bold>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel FlowDirection="LeftToRight" Orientation="Horizontal" Canvas.Top="30" Height="25">
|
||||
<TextBlock FontSize="14" Padding="25 0 0 0" Foreground="#bbbbbb" Text="{Binding ClassroomEntity.ClassSubHead,Mode=OneTime}"></TextBlock>
|
||||
<TextBlock FontSize="14" Padding="15 0 0 0" Foreground="#bbbbbb" Text="当前教室共有:"></TextBlock>
|
||||
<TextBlock FontSize="14" Foreground="#3d7cf9" Text="{Binding StudentCount,Mode=OneWay}"></TextBlock>
|
||||
<TextBlock FontSize="14" Padding="3 0 0 0" Foreground="#bbbbbb" Text="人"></TextBlock>
|
||||
</StackPanel>
|
||||
</Canvas>
|
||||
<!--右方聊天学员面板-->
|
||||
<Canvas DockPanel.Dock="Right" Width="280" Background="#2f3035">
|
||||
</Canvas>
|
||||
<!--下方教程面板-->
|
||||
<Canvas DockPanel.Dock="Bottom" Height="30" Background="#2a2b30">
|
||||
</Canvas>
|
||||
<!--下方设置面板-->
|
||||
<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="" />
|
||||
</Canvas>
|
||||
<!--中间面板-->
|
||||
<Canvas Background="#151618">
|
||||
|
||||
</Canvas>
|
||||
</DockPanel>
|
||||
</Canvas>
|
||||
</Metro:MetroWindow>
|
|
@ -0,0 +1,49 @@
|
|||
using AduSkin.Controls.Metro;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
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.Shapes;
|
||||
using System.Linq;
|
||||
|
||||
namespace JianGongYun.TRTC.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// LiveWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class LiveWindow : MetroWindow
|
||||
{
|
||||
ViewModels.LiveWindowViewModel LiveWindowViewModel;
|
||||
public LiveWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
LiveWindowViewModel =new ViewModels.LiveWindowViewModel();
|
||||
this.DataContext = LiveWindowViewModel;
|
||||
BorderBrush = new SolidColorBrush(color: Color.FromRgb(42, 43, 48));//窗口标题背景颜色
|
||||
|
||||
}
|
||||
private void aaaa(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LiveWindowViewModel.StudentCount++;
|
||||
}
|
||||
|
||||
//设置按钮
|
||||
private void Setting_Btn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var settingWindow = SettingWindow.GetInstance();
|
||||
settingWindow.Show();
|
||||
if (settingWindow.WindowState != WindowState.Normal)
|
||||
{
|
||||
settingWindow.WindowState = WindowState.Normal;
|
||||
}
|
||||
settingWindow.Topmost = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<Metro:MetroWindow x:Class="JianGongYun.TRTC.Windows.SettingWindow"
|
||||
xmlns:Metro="clr-namespace:AduSkin.Controls.Metro;assembly=AduSkin"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:JianGongYun.TRTC.Windows"
|
||||
mc:Ignorable="d"
|
||||
ResizeMode="NoResize"
|
||||
Title="设置" Height="380" Width="600">
|
||||
<Metro:MetroWindow.Resources>
|
||||
|
||||
<DataTemplate x:Key="CusHeaderTitle1">
|
||||
<TextBlock Foreground="#aaaaaa" FontWeight="Bold" Background="Transparent">音频设置</TextBlock>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="CusHeaderTitle2">
|
||||
<TextBlock Foreground="#aaaaaa" FontWeight="Bold" Background="Transparent">录屏设置</TextBlock>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="CusHeaderTitle3">
|
||||
<TextBlock Foreground="#aaaaaa" FontWeight="Bold" Background="Transparent">直播设置</TextBlock>
|
||||
</DataTemplate>
|
||||
</Metro:MetroWindow.Resources>
|
||||
<Metro:AduNavigationPanel IndicatorStyle="{StaticResource LeftIndicatorStyle}" IndicatorItemContainerStyle="{StaticResource LeftIndicatorItemStyle}" x:Name="navigationPanel"
|
||||
Height="auto" Width="auto"
|
||||
IndicatorMargin="0" IndicatorHorizontalAlignment="Center"
|
||||
IndicatorSelectedIndex="0" IndicatorPlacement="Left">
|
||||
<Metro:MetroScrollViewer HorizontalScrollBarVisibility="Disabled">
|
||||
<StackPanel Background="#232428">
|
||||
<Metro:AduGroupBoxNor HeaderTemplate="{StaticResource CusHeaderTitle1}" 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:AduFlatButton Content="检测麦克风" x:Name="MicTestBtn" Click="TestMic" Width="100" DockPanel.Dock="Right" Margin=" 11 0 10 0" Type="info" />
|
||||
<Metro:AduComboBox ItemsSource="{Binding MicList,Mode=OneWay}" DisplayMemberPath="Text" SelectedValuePath="Id" SelectedValue="{Binding CurrentMic,Mode=TwoWay}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}"></Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 麦采集音量</TextBlock>
|
||||
<Metro:AduFlatSilder x:Name="Slider1" DecreaseColor="#3e7fff" IncreaseColor="#aaaaaa" Maximum="100" Value="{Binding MicVolume}" Margin="0 0 10 0" Height="17"/>
|
||||
</DockPanel>
|
||||
<DockPanel Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 音频来源</TextBlock>
|
||||
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding AudioSource}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
|
||||
<ComboBoxItem Content="仅麦克风" Tag="1"/>
|
||||
<ComboBoxItem Content="麦和系统声音" Tag="2" />
|
||||
</Metro:AduComboBox>
|
||||
</DockPanel>
|
||||
<DockPanel Visibility="{Binding ShowSytemGatherSlider}" Style="{StaticResource SettingItem}">
|
||||
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 系统采集音量</TextBlock>
|
||||
<Metro:AduFlatSilder x:Name="Slider2" DecreaseColor="#3e7fff" IncreaseColor="#aaaaaa" Maximum="100" Value="{Binding SytemGatherVolume}" Margin="0 0 10 0" Height="17"/>
|
||||
</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>
|
||||
<Metro:AduGroupBoxNor HeaderTemplate="{StaticResource CusHeaderTitle3}" Header="直播设置" HeaderBackground="Transparent" BorderThickness="0" BorderBrush="{StaticResource DefaultBorderBrush}" FontSize="14" Height="380" HeaderPadding="10,6">
|
||||
|
||||
</Metro:AduGroupBoxNor>
|
||||
</StackPanel>
|
||||
</Metro:MetroScrollViewer>
|
||||
</Metro:AduNavigationPanel>
|
||||
</Metro:MetroWindow>
|
|
@ -0,0 +1,91 @@
|
|||
using AduSkin.Controls.Metro;
|
||||
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.Shapes;
|
||||
|
||||
namespace JianGongYun.TRTC.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// SettingWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class SettingWindow : MetroWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// 单例
|
||||
/// </summary>
|
||||
private static SettingWindow _Instance;
|
||||
public static SettingWindow GetInstance()
|
||||
{
|
||||
if (_Instance == null)
|
||||
{
|
||||
_Instance = new SettingWindow();
|
||||
}
|
||||
return _Instance;
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
_Instance = null;
|
||||
if (micTesting)//关闭麦克风测试
|
||||
{
|
||||
LiveClassroom.lTXDeviceManager.stopMicDeviceTest();
|
||||
}
|
||||
base.OnClosed(e);
|
||||
}
|
||||
ViewModels.SettingWindowViewModel mode = ViewModels.SettingWindowViewModel.GetInstance();
|
||||
private SettingWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
BorderBrush = new SolidColorBrush(color: Color.FromRgb(42, 43, 48));//窗口标题背景颜色
|
||||
this.DataContext = mode;
|
||||
}
|
||||
|
||||
bool micTesting = false;
|
||||
private void TestMic(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (micTesting)
|
||||
{
|
||||
LiveClassroom.lTXDeviceManager.stopMicDeviceTest();
|
||||
this.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
this.MicTestBtn.Content = "检测麦克风";
|
||||
this.MicTestBtn.Type = AduSkin.Controls.FlatButtonSkinEnum.info;
|
||||
micTesting = false;
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LiveClassroom.lTXDeviceManager.startMicDeviceTest(1000) == 0)
|
||||
{
|
||||
this.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
this.MicTestBtn.Content = "停止检测";
|
||||
this.MicTestBtn.Type = AduSkin.Controls.FlatButtonSkinEnum.error;
|
||||
micTesting = true;
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
AduMessageBox.Show("测试失败", "提醒");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnActivated(EventArgs e)
|
||||
{
|
||||
base.OnActivated(e);
|
||||
//滑动条颜色前台设置无效,手动调用才行
|
||||
var sliderColor = (SolidColorBrush)(new BrushConverter().ConvertFrom("#3e7fff"));
|
||||
Slider1.DecreaseColor = sliderColor;
|
||||
Slider2.DecreaseColor = sliderColor;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,40 +21,45 @@
|
|||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<ListBox ItemsSource="{Binding AllControlViewSource.View}" BorderThickness="0" Background="#2F3035" SelectedItem="{Binding CurrentShowControl}">
|
||||
<ListBox.Resources>
|
||||
<Style TargetType="ListBoxItem">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
</Style>
|
||||
</ListBox.Resources>
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border MinHeight="40" Width="245" Background="#00000000" x:Name="Bd" BorderBrush="#2F3035" BorderThickness="0 1 0 0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{Binding Title}" Foreground="White" Margin="20,0" VerticalAlignment="Center" HorizontalAlignment="Left"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True">
|
||||
<Setter TargetName="Bd" Property="Background" Value="#3E7FFF" />
|
||||
</DataTrigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsMouseOver" Value="True" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter TargetName="Bd" Property="Background" Value="WhiteSmoke" />
|
||||
</MultiTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<Canvas x:Name="CanvasContent">
|
||||
<ListBox Height="{Binding ElementName=CanvasContent,Path=ActualHeight}" ItemsSource="{Binding AllControlViewSource.View}" BorderThickness="0" Background="#2F3035" SelectedItem="{Binding CurrentShowControl}">
|
||||
<ListBox.Resources>
|
||||
<Style TargetType="ListBoxItem">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
</Style>
|
||||
</ListBox.Resources>
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border MinHeight="40" Width="245" Background="#00000000" x:Name="Bd" BorderBrush="#2F3035" BorderThickness="0 1 0 0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{Binding Title}" Foreground="White" Margin="20,0" VerticalAlignment="Center" HorizontalAlignment="Left"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True">
|
||||
<Setter TargetName="Bd" Property="Background" Value="#3E7FFF" />
|
||||
</DataTrigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsMouseOver" Value="True" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter TargetName="Bd" Property="Background" Value="WhiteSmoke" />
|
||||
</MultiTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<!--测试按钮-->
|
||||
<Metro:AduFlatButton Content="直播窗口测试弹出" Click="LiveTest_Click" Canvas.Bottom="100" Canvas.Left="77"></Metro:AduFlatButton>
|
||||
<!--测试按钮结束-->
|
||||
</Canvas>
|
||||
</Grid>
|
||||
</Border>
|
||||
<Grid Grid.Column="1">
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using JianGongYun.TRTC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
@ -21,5 +22,17 @@ namespace JianGongYun.Views
|
|||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void LiveTest_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LiveClassroom.EnterTheClassroom(Window.GetWindow(this),
|
||||
new TRTC.Models.ClassroomEntity
|
||||
{
|
||||
ClassHead = "课程1",
|
||||
ClassSubHead = "章节1",
|
||||
TeacherId = "53245345",
|
||||
TeacherName = "王大锤"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue