Skip to content

Commit

Permalink
Added back toggle route posibilites.
Browse files Browse the repository at this point in the history
  • Loading branch information
oddbear committed Jan 29, 2022
1 parent aa1e03a commit 380ca33
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 185 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,10 @@
This project is to be able to control a Revelator io24 interface through an API.
That way we can have plugins for Stream Deck, Touch Portal and Loupedeck... and more.

**This project is in the early stages, and a proof-of-concept only, don't expect it to be stable at this point**
**This project is in the early stages, and a proof-of-concept only, don't expect it to be stable at this point**

## How to test
- Go to [Releases](https://github.com/oddbear/Revelator.io24.Api/releases/tag/v0.0.1-pre)
- Download zip file under Assets
- Unzip
- Run `Revelator.io24.Wpf.exe`
18 changes: 18 additions & 0 deletions Revelator.io24.Api/Attributes/RouteNameAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Revelator.io24.Api.Enums;

namespace Revelator.io24.Api.Attributes
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class RouteNameAttribute : Attribute
{
public string RouteName { get; }

public RouteType RouteType { get; }

public RouteNameAttribute(string routeName, RouteType routeType = RouteType.Mute)
{
RouteName = routeName;
RouteType = routeType;
}
}
}
11 changes: 11 additions & 0 deletions Revelator.io24.Api/Enums/Headphones.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Revelator.io24.Api.Enums
{
public enum Headphones : ushort
{
//Route: "global/phonesSrc"
Unknown = ushort.MaxValue,
Main = 0, // 0: 0x00, 0x00, 0.0f
MixA = 16128, //16128: 0x00, 0x3F, 0.5f
MixB = 16256 //16256: 0x80, 0x3F, 1.0f
}
}
15 changes: 15 additions & 0 deletions Revelator.io24.Api/Enums/RouteType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Revelator.io24.Api.Enums
{
/// <summary>
/// Some values has inverted On/Off state.
/// This is becuase some has mute states, and some has assign states.
/// IsMuted != IsAssigned
/// IsMuted: Ends with /mute
/// IsAssigned: Ends contains /assign_aux then a number.
/// </summary>
public enum RouteType
{
Mute,
Assign
}
}
4 changes: 2 additions & 2 deletions Revelator.io24.Api/Models/SynchronizeModel.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Revelator.io24.Api.Models.Json;
using Revelator.io24.Api.Services;
using Revelator.io24.Api.Enums;
using Revelator.io24.Api.Models.Json;

namespace Revelator.io24.Api.Models
{
Expand Down
5 changes: 4 additions & 1 deletion Revelator.io24.Api/Services/RoutingModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
namespace Revelator.io24.Api.Services
using Revelator.io24.Api.Attributes;
using Revelator.io24.Api.Enums;

namespace Revelator.io24.Api.Services
{
public class RoutingModel
{
Expand Down
124 changes: 5 additions & 119 deletions Revelator.io24.Api/Services/UpdateService.cs
Original file line number Diff line number Diff line change
@@ -1,45 +1,12 @@
using Revelator.io24.Api.Helpers;
using Revelator.io24.Api.Attributes;
using Revelator.io24.Api.Enums;
using Revelator.io24.Api.Helpers;
using Revelator.io24.Api.Models;
using System.Reflection;
using System.Text;

namespace Revelator.io24.Api.Services
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class RouteNameAttribute : Attribute
{
public string RouteName { get; }

public RouteType RouteType { get; }

public RouteNameAttribute(string routeName, RouteType routeType = RouteType.Mute)
{
RouteName = routeName;
RouteType = routeType;
}
}

/// <summary>
/// Some values has inverted On/Off state.
/// This is becuase some has mute states, and some has assign states.
/// IsMuted != IsAssigned
/// IsMuted: Ends with /mute
/// IsAssigned: Ends contains /assign_aux then a number.
/// </summary>
public enum RouteType
{
Mute,
Assign
}

public enum Headphones : ushort
{
Unknown = ushort.MaxValue,
Main = 0, //0: 0x00, 0x00
MixA = 16128, //16128: 0x00, 0x3f
MixB = 16256 //16256: 0x80, 0x3f
}

public class UpdateService
{
public event EventHandler? RoutingUpdated;
Expand Down Expand Up @@ -119,64 +86,7 @@ private void _communicationService_RouteChange(string route, ushort state)
}
}

public void SetHeadphonesToMix(string name)
{
var message = new byte[35];

//Header [0..4]:
var header = PackageHelper.GetHeader();
PackageHelper.ApplyBytes(message, header, 0);

//Length [4..6]:
message[4] = 0x1d; // (0x1d, 0x00) -> 29
message[5] = 0x00;

//MessageType [6..8]:
var messageType = Encoding.ASCII.GetBytes("PV");
PackageHelper.ApplyBytes(message, messageType, 6);

//CustomBytes [8..12]:
var customBytes = PackageHelper.GetDeviceCustomBytes();
PackageHelper.ApplyBytes(message, customBytes, 8);

//Text [12..28]:
var text = Encoding.ASCII.GetBytes("global/phonesSrc");
PackageHelper.ApplyBytes(message, text, 12);

//Empty [28..33]:

//State [33..35]:
if (name == "main_phones")
{
//BitConverter.GetBytes(0.0f)
message[33] = 0x00;
message[34] = 0x00;
Routing.HeadphonesSource = Headphones.Main;
}
else if (name == "mixA_phones")
{
//BitConverter.GetBytes(0.5f)
message[33] = 0x00;
message[34] = 0x3f;
Routing.HeadphonesSource = Headphones.MixA;
}
else if (name == "mixB_phones")
{
//BitConverter.GetBytes(1.0f)
message[33] = 0x80;
message[34] = 0x3f;
Routing.HeadphonesSource = Headphones.MixB;
}
else
{
return;
}
_communicationService.SendMessage(message);
}

private Dictionary<string, bool> _muted = new();

public void ToggleMute(string route, Action<string, bool> setNewState)
public void SetRouteValue(string route, ushort value)
{
var message = new List<byte>();

Expand Down Expand Up @@ -209,7 +119,7 @@ public void ToggleMute(string route, Action<string, bool> setNewState)
length += empty.Length;

//State [x+5..x+7]:
var state = GetMuteState(route);
var state = BitConverter.GetBytes(value); //Float, but on two bytes (ints are AA,BB,00,00 this is 00,00,AA,BB
message.AddRange(state);
length += state.Length;

Expand All @@ -219,30 +129,6 @@ public void ToggleMute(string route, Action<string, bool> setNewState)
message[5] = lengthBytes[1];

_communicationService.SendMessage(message.ToArray());
_muted[route] = !_muted[route];
setNewState(route, !_muted[route]);
}

private byte[] GetMuteState(string route)
{
if (!_muted.ContainsKey(route))
_muted[route] = false;

var state = _muted[route];
if (route.EndsWith("/mute"))
{
//state is mute state
return state
? new byte[] { 0x00, 0x00 }
: new byte[] { 0x80, 0x3f };
}
else
{
//state is assign state
return state
? new byte[] { 0x80, 0x3f }
: new byte[] { 0x00, 0x00 };
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Revelator.io24.Api.Services;
using Revelator.io24.Api.Enums;
using System;
using System.Globalization;
using System.Windows.Data;
Expand Down
52 changes: 51 additions & 1 deletion Revelator.io24.Wpf/MainViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
using Revelator.io24.Api.Models;
using Revelator.io24.Api.Attributes;
using Revelator.io24.Api.Enums;
using Revelator.io24.Api.Models;
using Revelator.io24.Api.Services;
using Revelator.io24.Wpf.Commands;
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Windows.Input;

namespace Revelator.io24.Wpf
{
Expand All @@ -16,6 +22,9 @@ public class MainViewModel : INotifyPropertyChanged
public FatChannelMonitorModel FatChannelValues => _monitorService.FatChannel;
public RoutingModel RoutingValues => _updateService.Routing;

private readonly DelegateCommand _routeChangeCommand;
public ICommand RouteChangeCommand => _routeChangeCommand;

public MainViewModel(MonitorService monitorService, UpdateService updateService)
{
_monitorService = monitorService ?? throw new ArgumentNullException(nameof(monitorService));
Expand All @@ -25,6 +34,47 @@ public MainViewModel(MonitorService monitorService, UpdateService updateService)
_monitorService.FatChannelUpdated += (sender, args) => OnPropertyChanged(nameof(FatChannelValues));

_updateService.RoutingUpdated += (sender, args) => OnPropertyChanged(nameof(RoutingValues));

_routeChangeCommand = new DelegateCommand(OnRouteChangeRequest);
}

private void OnRouteChangeRequest(object commandParameter)
{
if (commandParameter is not string commandParameterString)
return;

var split = commandParameterString.Split(':');
var route = split[0];
if (route == "global/phonesSrc")
{
var value = ushort.Parse(split[1]);
_updateService.SetRouteValue(route, value);
}
else
{
var properties = typeof(RoutingModel).GetProperties();
var routeProperty = properties
.Select(property => new { property, attribute = property.GetCustomAttribute<RouteNameAttribute>() })
.FirstOrDefault(obj => obj.attribute?.RouteName == route);

if (routeProperty is null)
return;

var property = routeProperty.property;
var attribute = routeProperty.attribute;

var value = (bool)property.GetValue(RoutingValues);
if (attribute.RouteType == RouteType.Mute)
{
ushort v = (ushort)(value ? 16256 : 0);
_updateService.SetRouteValue(route, v);
}
else
{
ushort v = (ushort)(value ? 0 : 16256);
_updateService.SetRouteValue(route, v);
}
}
}

protected void OnPropertyChanged(string? name = null)
Expand Down
21 changes: 21 additions & 0 deletions Revelator.io24.Wpf/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,48 +144,69 @@
<Label Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" HorizontalContentAlignment="Center">Stream Mix B</Label>

<Button Grid.Row="1" Grid.Column="1" x:Name="line_ch1_mute"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="line/ch1/mute"
Background="{Binding Path=RoutingValues.Main_MicL, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="1" Grid.Column="2" x:Name="line_ch2_mute"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="line/ch2/mute"
Background="{Binding Path=RoutingValues.Main_MicR, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="1" Grid.Column="3" x:Name="return_ch1_mute"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="return/ch1/mute"
Background="{Binding Path=RoutingValues.Main_Playback, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="1" Grid.Column="4" x:Name="return_ch2_mute"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="return/ch2/mute"
Background="{Binding Path=RoutingValues.Main_VirtualA, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="1" Grid.Column="5" x:Name="return_ch3_mute"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="return/ch3/mute"
Background="{Binding Path=RoutingValues.Main_VirtualB, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="1" Grid.Column="6" x:Name="main_ch1_mute"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="main/ch1/mute"
Background="{Binding Path=RoutingValues.Main_Mix, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="1" Grid.Column="7" x:Name="main_phones"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="global/phonesSrc:0"
Background="{Binding Path=RoutingValues.HeadphonesSource, Converter={StaticResource headphonesStateColorConverter}, ConverterParameter=0}"></Button>

<Button Grid.Row="2" Grid.Column="1" x:Name="line_ch1_assign_aux1"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="line/ch1/assign_aux1"
Background="{Binding Path=RoutingValues.MixA_MicL, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="2" Grid.Column="2" x:Name="line_ch2_assign_aux1"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="line/ch2/assign_aux1"
Background="{Binding Path=RoutingValues.MixA_MicR, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="2" Grid.Column="3" x:Name="return_ch1_assign_aux1"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="return/ch1/assign_aux1"
Background="{Binding Path=RoutingValues.MixA_Playback, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="2" Grid.Column="4" x:Name="return_ch2_assign_aux1"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="return/ch2/assign_aux1"
Background="{Binding Path=RoutingValues.MixA_VirtualA, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="2" Grid.Column="5" x:Name="return_ch3_assign_aux1"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="return/ch3/assign_aux1"
Background="{Binding Path=RoutingValues.MixA_VirtualB, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="2" Grid.Column="6" x:Name="aux_ch1_mute"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="aux/ch1/mute"
Background="{Binding Path=RoutingValues.MixA_Mix, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="2" Grid.Column="7" x:Name="mixA_phones"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="global/phonesSrc:16128"
Background="{Binding Path=RoutingValues.HeadphonesSource, Converter={StaticResource headphonesStateColorConverter}, ConverterParameter=16128}"></Button>

<Button Grid.Row="3" Grid.Column="1" x:Name="line_ch1_assign_aux2"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="line/ch1/assign_aux2"
Background="{Binding Path=RoutingValues.MixB_MicL, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="3" Grid.Column="2" x:Name="line_ch2_assign_aux2"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="line/ch2/assign_aux2"
Background="{Binding Path=RoutingValues.MixB_MicR, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="3" Grid.Column="3" x:Name="return_ch1_assign_aux2"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="return/ch1/assign_aux2"
Background="{Binding Path=RoutingValues.MixB_Playback, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="3" Grid.Column="4" x:Name="return_ch2_assign_aux2"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="return/ch2/assign_aux2"
Background="{Binding Path=RoutingValues.MixB_VirtualA, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="3" Grid.Column="5" x:Name="return_ch3_assign_aux2"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="return/ch3/assign_aux2"
Background="{Binding Path=RoutingValues.MixB_VirtualB, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="3" Grid.Column="6" x:Name="aux_ch2_mute"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="aux/ch2/mute"
Background="{Binding Path=RoutingValues.MixB_Mix, Converter={StaticResource routingStateColorConverter}}" />
<Button Grid.Row="3" Grid.Column="7" x:Name="mixB_phones"
Command="{Binding Path=RouteChangeCommand}" CommandParameter="global/phonesSrc:16256"
Background="{Binding Path=RoutingValues.HeadphonesSource, Converter={StaticResource headphonesStateColorConverter}, ConverterParameter=16256}" />
</Grid>
</GroupBox>
Expand Down
Loading

0 comments on commit 380ca33

Please sign in to comment.