Initial check-in of module qController

This commit is contained in:
2018-06-01 15:09:01 -05:00
commit 30e23418a6
126 changed files with 10486 additions and 0 deletions
BIN
View File
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="qController.App">
<Application.Resources>
<!-- Application resource dictionary -->
</Application.Resources>
</Application>
+32
View File
@@ -0,0 +1,32 @@
using Xamarin.Forms;
namespace qController
{
public partial class App : Application
{
public static INavigation iNav;
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new qControllerPage());
iNav = MainPage.Navigation;
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
@@ -0,0 +1,20 @@
using System;
using Xamarin.Forms;
namespace qController
{
public class QButton : Button
{
public string OSCCommand
{
get;
set;
}
public QButton(string text, string cmd)
{
Text = text;
OSCCommand = cmd;
}
}
}
@@ -0,0 +1,40 @@
using System;
using System.Net;
using System.Net.NetworkInformation;
using Xamarin.Forms;
namespace qController
{
public class QInstance : ViewCell
{
public string name { get; set; }
public string address { get; set; }
public QInstance()
{
}
public QInstance(string tName, string tAddress)
{
name = tName;
address = tAddress;
}
public bool IsReachable()
{
/*try
{
IPAddress instanceIP = IPAddress.Parse(address);
Ping p = new System.Net.NetworkInformation.Ping();
PingReply reply = p.Send(instanceIP);
return reply.Status == IPStatus.Success ? true : false;
}
catch
{
return false;
}*/
return true;
}
}
}
@@ -0,0 +1,111 @@
using System;
using Xamarin.Forms;
namespace qController
{
public class QInstanceCell : ViewCell
{
public QInstanceCell()
{
Label nameLabel = new Label();
Label addressLabel = new Label();
Image connectButton = new Image();
Image deleteButton = new Image();
var connectTapGesture = new TapGestureRecognizer();
var deleteTapGesture = new TapGestureRecognizer();
connectTapGesture.Tapped += Connect;
connectButton.GestureRecognizers.Add(connectTapGesture);
deleteTapGesture.Tapped += Delete;
deleteButton.GestureRecognizers.Add(deleteTapGesture);
InitItems();
//SET BINDINGS
nameLabel.SetBinding(Label.TextProperty, new Binding("name"));
addressLabel.SetBinding(Label.TextProperty,new Binding("address"));
Grid mainG = new Grid
{
//Padding = new Thickness(10),
RowDefinitions = {
new RowDefinition{Height = GridLength.Auto},
new RowDefinition{Height = GridLength.Auto}
},
ColumnDefinitions = {
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)},
new ColumnDefinition{Width = new GridLength(4,GridUnitType.Star)},
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)}
}
};
mainG.Children.Add(nameLabel, 1, 0);
mainG.Children.Add(addressLabel,1,1);
mainG.Children.Add(connectButton,2,0);
Grid.SetRowSpan(connectButton,2);
mainG.Children.Add(deleteButton, 0, 0);
Grid.SetRowSpan(deleteButton,2);
Frame f = new Frame
{
Content = mainG,
OutlineColor = Color.Black,
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
Padding = 30,
Margin = new Thickness(10,10,10,10),
CornerRadius=20
};
f.BackgroundColor = Color.FromHex("D8D8D8");
View = f;
void InitItems()
{
nameLabel.HorizontalTextAlignment = TextAlignment.Center;
nameLabel.VerticalTextAlignment = TextAlignment.End;
nameLabel.FontAttributes = FontAttributes.Bold;
nameLabel.FontSize = 20;
connectButton.HorizontalOptions = LayoutOptions.CenterAndExpand;
connectButton.VerticalOptions = LayoutOptions.CenterAndExpand;
connectButton.Source = "connect.png";
deleteButton.HorizontalOptions = LayoutOptions.CenterAndExpand;
deleteButton.VerticalOptions = LayoutOptions.CenterAndExpand;
deleteButton.Source = "delete.png";
addressLabel.HorizontalTextAlignment = TextAlignment.Center;
addressLabel.VerticalTextAlignment = TextAlignment.Start;
}
void Delete(object sender, EventArgs e)
{
Console.WriteLine("Delete " + nameLabel.Text + "," + addressLabel.Text + " Pressed");
QStorage.RemoveInstance(nameLabel.Text,addressLabel.Text);
}
void Connect(object sender, EventArgs e)
{
App.iNav.PushModalAsync(new NavigationPage(new ControlPage(nameLabel.Text,addressLabel.Text)));
Console.WriteLine("Connect To" + nameLabel.Text + " Pressed");
}
}
}
}
@@ -0,0 +1,76 @@
using System;
using Xamarin.Forms;
namespace qController
{
public class QSelectedCueCell : Frame
{
Label name;
Label number;
Label type;
Label notes;
public QSelectedCueCell()
{
Padding = new Thickness(5);
CornerRadius = 20;
BackgroundColor = Color.FromHex("D8D8D8");
Grid mainG = new Grid
{
Padding = new Thickness(0),
RowDefinitions = {
new RowDefinition{Height = GridLength.Auto},
new RowDefinition{Height = GridLength.Auto},
new RowDefinition{Height = GridLength.Auto}
},
ColumnDefinitions = {
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)},
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)},
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)},
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)},
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)}
}
};
number = new Label { Text = "N/A"};
number.FontAttributes = FontAttributes.Bold;
number.FontSize = 30;
number.Margin = new Thickness(5);
name = new Label { Text = "N/A" };
name.FontAttributes = FontAttributes.Bold;
name.HorizontalTextAlignment = TextAlignment.Center;
name.FontSize = 20;
name.Margin = new Thickness(0);
type = new Label { Text = "N/A" };
type.FontAttributes = FontAttributes.Bold;
type.VerticalTextAlignment = TextAlignment.Center;
type.HorizontalTextAlignment = TextAlignment.Center;
type.Margin = new Thickness(5);
notes = new Label { Text = "Viewing Notes Currently Unavailable" };
notes.HorizontalTextAlignment = TextAlignment.Center;
notes.Margin = new Thickness(0, 0, 0, 10);
mainG.Children.Add(number, 0, 0);
mainG.Children.Add(type, 4, 0);
mainG.Children.Add(name, 0, 1);
mainG.Children.Add(notes, 0, 2);
Grid.SetColumnSpan(name, 5);
Grid.SetColumnSpan(notes,5);
Margin = new Thickness(10);
Content = mainG;
}
public void UpdateSelectedCue(QCue cue)
{
name.Text = cue.name;
number.Text = cue.number;
type.Text = cue.type;
//notes.Text = cue.notes;
}
}
}
@@ -0,0 +1,129 @@
using System;
using Newtonsoft.Json.Linq;
using Xamarin.Forms;
namespace qController
{
public class QSelectedCueOptionsCell : Frame
{
void AudioLevelsUpdated(object source, AudioLevelArgs args)
{
Device.BeginInvokeOnMainThread(() => {
levels = args.levels;
if (mainSlider != null)
{
mainSlider.Value = (double)levels[0];
}
if (leftSlider != null)
{
leftSlider.Value = (double)levels[1];
}
if (rightSlider != null)
{
rightSlider.Value = (double)levels[2];
}
});
}
Label type;
JToken levels;
Slider mainSlider;
Slider leftSlider;
Slider rightSlider;
public QSelectedCueOptionsCell(QController qController)
{
qController.qParser.AudioLevelsUpdated += AudioLevelsUpdated;
Padding = new Thickness(5);
CornerRadius = 20;
BackgroundColor = Color.FromHex("D8D8D8");
Grid mainG = new Grid
{
Padding = new Thickness(0),
RowDefinitions = {
new RowDefinition{Height = GridLength.Auto},
new RowDefinition{Height = GridLength.Auto},
new RowDefinition{Height = GridLength.Auto}
},
ColumnDefinitions = {
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)},
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)},
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)},
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)},
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)}
}
};
type = new Label { Text = "" };
mainSlider = new Slider
{
Minimum = -60,
Maximum = 12
};
mainSlider.ValueChanged += (sender, args) =>
{
Console.WriteLine(String.Format("The Main Slider value is {0}", args.NewValue));
qController.qSender.sendArgs("/cue/selected/sliderLevel/0", (float)args.NewValue);
};
leftSlider = new Slider
{
Minimum = -60,
Maximum = 12
};
leftSlider.ValueChanged += (sender, args) =>
{
Console.WriteLine(String.Format("The Left Slider value is {0}", (float)args.NewValue));
qController.qSender.sendArgs("/cue/selected/sliderLevel/1", (float)args.NewValue);
};
rightSlider = new Slider
{
Minimum = -60,
Maximum = 12
};
rightSlider.ValueChanged += (sender, args) =>
{
Console.WriteLine(String.Format("The Right Slider value is {0}", args.NewValue));
qController.qSender.sendArgs("/cue/selected/sliderLevel/2", (float)args.NewValue);
};
mainG.Children.Add(mainSlider, 1, 0);
mainG.Children.Add(leftSlider, 1, 1);
mainG.Children.Add(rightSlider, 1, 2);
Grid.SetColumnSpan(mainSlider, 4);
Grid.SetColumnSpan(leftSlider, 4);
Grid.SetColumnSpan(rightSlider, 4);
Label mainLabel = new Label {
Text = "MAIN",
VerticalTextAlignment = TextAlignment.Center,
HorizontalTextAlignment = TextAlignment.Center
};
Label leftLabel = new Label
{
Text = "LEFT",
VerticalTextAlignment = TextAlignment.Center,
HorizontalTextAlignment = TextAlignment.Center
};
Label rightLabel = new Label
{
Text = "RIGHT",
VerticalTextAlignment = TextAlignment.Center,
HorizontalTextAlignment = TextAlignment.Center
};
mainG.Children.Add(mainLabel, 0, 0);
mainG.Children.Add(leftLabel, 0, 1);
mainG.Children.Add(rightLabel, 0, 2);
Content = mainG;
}
public void UpdateSelectedCue(QCue cue)
{
type.Text = cue.type;
}
}
}
@@ -0,0 +1,18 @@
using System;
using System.Net;
namespace qController
{
public class IPHelper
{
public IPHelper()
{
}
public static bool IsValidAddress(string ipString){
if ((ipString.Split('.').Length - 1) != 3) return false;
IPAddress address;
return IPAddress.TryParse(ipString, out address);
}
}
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Xamarin.Forms;
namespace qController
{
public class QController
{
public QSender qSender;
QReceiver qReceiver;
QUpdater qUpdater;
public QParser qParser;
QCue selectedCue;
public QController(string address, int port)
{
qSender = new QSender(address, port);
qReceiver = new QReceiver(port+1, this);
qParser = new QParser();
qUpdater = new QUpdater(this);
qUpdater.Start();
qParser.SelectedCueUpdated += this.OnSelectedCueUpdated;
qReceiver.PacketReceived += qParser.OnPacketReceived;
}
public void sendCommand(string cmd){
qSender.sendString(cmd);
}
public void updateCueValue(QCue cue, string property, object newValue){
// qSender.sendArgs("/cue_id/"+cue.uniqueID+"/"+property, newValue);
}
public void OnSelectedCueUpdated(object source, CueEventArgs args)
{
selectedCue = args.SelectedCue;
//Console.WriteLine("Selected Cue Updated: Name=" + selectedCue.listName);
}
public void Kill(){
qReceiver.Close();
qUpdater.Kill();
}
}
}
@@ -0,0 +1,26 @@
//Currently deprecated would like to resurrect
using System;
using System.Collections.Generic;
using Zeroconf;
namespace qController
{
public class QFinder
{
public QFinder()
{
}
public async void SearchForWorkspaces()
{
IReadOnlyList<IZeroconfHost> results = await ZeroconfResolver.ResolveAsync("_qlab._udp.local.");
foreach (var result in results){
Console.WriteLine(result.IPAddress);
}
Console.WriteLine("Done");
}
}
}
@@ -0,0 +1,91 @@
using System;
using Rug.Osc;
using Newtonsoft.Json.Linq;
namespace qController
{
public class CueEventArgs : EventArgs
{
public QCue SelectedCue
{
get;
set;
}
}
public class AudioLevelArgs : EventArgs
{
public JToken levels
{
get;
set;
}
}
public class QParser
{
public QParser()
{
}
public delegate void SelectedCueUpdatedHandler(object source, CueEventArgs args);
public delegate void AudioLevelsUpdatedHandler(object source, AudioLevelArgs args);
public event SelectedCueUpdatedHandler SelectedCueUpdated;
public event AudioLevelsUpdatedHandler AudioLevelsUpdated;
public void ParsePacket(OscPacket packet){
OscMessage msg = (OscMessage)packet;
if (msg.Address.Contains("selectedCues"))
ParseSelectedCueInfo(msg);
else if (msg.Address.Contains("notes"))
ParseNoteInfo(msg);
else if (msg.Address.Contains("levels"))
ParseLevelInfo(msg);
}
public void OnPacketReceived(object source, PacketEventArgs args){
//Console.WriteLine("Packet Received");
ParsePacket(args.Packet);
}
public void ParseSelectedCueInfo(OscMessage msg){
JArray selectedCues = (JArray)OSC2JSON(msg);
if(selectedCues.Count > 0){
foreach(JObject item in selectedCues){
QCue parsedCue = new QCue(item);
OnSelectedCueUpdated(parsedCue);
}
}else{
Console.WriteLine("No Cues Selected");
}
}
public void ParseNoteInfo(OscMessage msg){
//JToken cueInfo = OSC2JSON(msg);
}
public void ParseLevelInfo(OscMessage msg){
JToken levels = OSC2JSON(msg)[0];
OnAudioLevelsUpdated(levels);
}
public JToken OSC2JSON(OscMessage Msg){
JObject json = JObject.Parse(Msg.ToArray()[0].ToString());
return json.GetValue("data");
}
protected virtual void OnSelectedCueUpdated(QCue cue)
{
if (SelectedCueUpdated != null)
SelectedCueUpdated(this, new CueEventArgs() { SelectedCue = cue });
}
protected virtual void OnAudioLevelsUpdated(JToken audioLevels){
if (AudioLevelsUpdated != null)
AudioLevelsUpdated(this, new AudioLevelArgs { levels = audioLevels });
}
}
}
@@ -0,0 +1,80 @@
using System;
using Rug.Osc;
using System.Net;
using System.Threading;
namespace qController
{
public class PacketEventArgs : EventArgs{
public OscPacket Packet {
get;
set;
}
}
public class QReceiver
{
static OscReceiver qReceiver;
static Thread thread;
private QController owner;
public delegate void PacketReceivedHandler(object source, PacketEventArgs args);
public event PacketReceivedHandler PacketReceived;
public QReceiver(int port, QController ctrl)
{
qReceiver = new OscReceiver(port);
thread = new Thread(new ThreadStart(ListenLoop));
owner = ctrl;
qReceiver.Connect();
thread.Start();
}
public void ListenLoop()
{
Console.WriteLine("Loop Started");
try
{
while (qReceiver.State != OscSocketState.Closed)
{
// if we are in a state to recieve
if (qReceiver.State == OscSocketState.Connected)
{
// get the next message
// this will block until one arrives or the socket is closed
OscPacket packet = qReceiver.Receive();
OnPacketReceived(packet);
// Write the packet to the console
// DO SOMETHING HERE!
}
}
}
catch (Exception ex)
{
// if the socket was connected when this happens
// then tell the user
if (qReceiver.State == OscSocketState.Connected)
{
Console.WriteLine("Exception in listen loop");
Console.WriteLine(ex.Message);
}
}
Console.WriteLine("Loop Ended");
}
public void Close(){
qReceiver.Close();
thread.Abort();
}
protected virtual void OnPacketReceived(OscPacket pkt){
if (PacketReceived != null)
PacketReceived(this, new PacketEventArgs(){Packet = pkt});
}
}
}
@@ -0,0 +1,31 @@
using System;
using System.Net;
using Rug.Osc;
namespace qController
{
public class QSender
{
OscSender qSender;
public QSender(string address, int port)
{
IPAddress ipAddress = IPAddress.Parse(address);
qSender = new OscSender(ipAddress, port);
}
public void sendString(string address) {
qSender.Connect();
qSender.Send(new OscMessage(address,new object[]{}));
qSender.Close();
}
public void sendArgs(string msg, object args){
qSender.Connect();
qSender.Send(new OscMessage(msg,args));
qSender.Close();
}
}
}
@@ -0,0 +1,27 @@
using System;
using Xamarin.Forms;
namespace qController
{
public class QUpdater
{
private bool active = true;
private QController qController;
public QUpdater(QController controller)
{
qController = controller;
}
public void Start(){
active = true;
Device.StartTimer(TimeSpan.FromSeconds(0.01), () => {
qController.sendCommand("/selectedCues");
qController.sendCommand("/cue/selected/levels");
return active;
});
}
public void Kill(){
active = false;
}
}
}
+29
View File
@@ -0,0 +1,29 @@
using System;
using Newtonsoft.Json.Linq;
namespace qController
{
public class QCue
{
public string number;
public string uniqueID;
public bool flagged;
public string listName;
public string type;
public string colorName;
public string name;
public bool armed;
public QCue(JObject json){
//Console.WriteLine(json);
number = (string)json.GetValue("number");
uniqueID = (string)json.GetValue("uniqueID");
flagged = (bool)json.GetValue("flagged");
listName = (string)json.GetValue("listName");
type = (string)json.GetValue("type");
colorName = (string)json.GetValue("colorName");
name = (string)json.GetValue("name");
armed = (bool)json.GetValue("armed");
}
}
}
@@ -0,0 +1,12 @@
using Newtonsoft.Json.Linq;
namespace qController
{
public class QGroupCue : QCue
{
public QGroupCue(JObject json) : base(json)
{
}
}
}
@@ -0,0 +1,11 @@
using System;
namespace qController
{
public class QGrid
{
public QGrid()
{
}
}
}
@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Acr.Settings;
namespace qController
{
public class QStorage
{
public static ObservableCollection<QInstance> qInstances;
static QStorage(){
qInstances = (ObservableCollection<QInstance>)CrossSettings.Current.GetValue(new ObservableCollection<QInstance>().GetType(), "qInstances", null);
if (qInstances == null)
{
Console.WriteLine("No qInstance exists creating one");
qInstances = new ObservableCollection<QInstance>();
updateStorage();
}
}
public static void AddInstance(string name, string address){
if(!Contains(name,address)){
qInstances.Add(new QInstance(name, address));
}
}
public static void AddInstance(QInstance q){
qInstances.Add(q);
updateStorage();
}
public static void RemoveInstance(string name, string address){
foreach (var item in qInstances)
{
if(item.address == address && item.name == name){
RemoveInstance(item);
return;
}
}
}
public static void RemoveInstance(QInstance q){
qInstances.Remove(q);
updateStorage();
}
private static void updateStorage(){
CrossSettings.Current.SetValue("qInstances", qInstances);
}
public static bool Contains(string name, string address){
foreach (var item in qInstances)
{
if (item.name == name && item.address == address)
{
return true;
}
}
return false;
}
public bool IsEmpty(){
return qInstances.Count == 0;
}
}
}
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="qController.ControlPage">
<ContentPage.Content>
<StackLayout x:Name="sLayout">
<Grid x:Name="topBar" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image x:Name = "backButton" HorizontalOptions = "Start" Margin="20,10,20,10" Grid.Row="0" Grid.Column="0" />
</Grid>
</StackLayout>
</ContentPage.Content>
</ContentPage>
@@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using Rug.Osc;
using System.Collections;
namespace qController
{
public partial class ControlPage : ContentPage
{
QController qController;
Label instanceName = new Label();
QSelectedCueCell qCell;
QSelectedCueOptionsCell qSelectedCueOptions;
Grid mainG;
public ControlPage(string name, string address)
{
InitializeComponent();
qController = new QController(address, 53000);
qController.qParser.SelectedCueUpdated += SelectedCueUpdated;
NavigationPage.SetHasNavigationBar(this, false);
instanceName.Text = name;
InitGUI();
}
private void InitGUI()
{
instanceName.HorizontalTextAlignment = TextAlignment.Center;
instanceName.HorizontalOptions = LayoutOptions.CenterAndExpand;
instanceName.VerticalOptions = LayoutOptions.CenterAndExpand;
topBar.Children.Add(instanceName, 1, 0);
topBar.BackgroundColor = Color.FromHex("71AEFF");
BackgroundColor = Color.FromHex("4A4A4A");
backButton.Source = ImageSource.FromFile("back");
switch (Device.RuntimePlatform)
{
case Device.iOS:
backButton.Margin = new Thickness(20, 45, 20, 10);
instanceName.Margin = new Thickness(20, 45, 20, 10);
break;
}
Hashtable cmds = new Hashtable();
var backButtonGesture = new TapGestureRecognizer();
backButtonGesture.Tapped += Back;
backButton.GestureRecognizers.Add(backButtonGesture);
cmds.Add("Pause", "/pause");
cmds.Add("Resume", "/resume");
cmds.Add("Panic", "/panic");
cmds.Add("Next", "/select/next");
cmds.Add("Previous", "/select/previous");
cmds.Add("Preview", "/preview");
qCell = new QSelectedCueCell();
qSelectedCueOptions = new QSelectedCueOptionsCell(qController);
sLayout.Children.Add(qCell);
mainG = new Grid
{
Padding = new Thickness(0),
RowDefinitions = {
new RowDefinition{Height = GridLength.Auto},
new RowDefinition{Height = GridLength.Auto},
new RowDefinition{Height = GridLength.Auto}
},
ColumnDefinitions = {
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)},
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)},
new ColumnDefinition{Width = new GridLength(1,GridUnitType.Star)}
}
};
int row = 0;
int column = 0;
foreach (string cmd in cmds.Keys)
{
QButton b = new QButton(cmd,(string)cmds[cmd]);
b.Clicked += sendOSC;
if(cmd=="Panic")
{
b.BackgroundColor = Color.IndianRed;
}
else
{
b.BackgroundColor = Color.FromHex("D8D8D8");
}
b.TextColor = Color.Black;
mainG.Children.Add(b,column,row);
row++;
if(row == 3){
row = 0;
column = 2;
}
}
QButton goButton = new QButton("GO","/go");
goButton.Clicked += sendOSC;
goButton.BackgroundColor = Color.SeaGreen;
goButton.TextColor = Color.Black;
mainG.Children.Add(goButton,1,0);
Grid.SetRowSpan(goButton,3);
sLayout.Children.Add(mainG);
}
void sendOSC(object sender, EventArgs e)
{
qController.sendCommand(((QButton)sender).OSCCommand);
}
void Back(object sender, EventArgs e)
{
App.iNav.PopModalAsync();
}
public void SelectedCueUpdated(object sender, CueEventArgs e){
Device.BeginInvokeOnMainThread(()=>{
if (e.SelectedCue.type.Equals("Audio"))
{
//Console.WriteLine("CUE IS AN AUDIO CUE");
sLayout.Children.Add(qSelectedCueOptions);
}
else
{
//Console.WriteLine("CUE IS NOT AN AUDIO CUE");
sLayout.Children.Remove(qSelectedCueOptions);
}
qCell.UpdateSelectedCue(e.SelectedCue);
});
}
protected override void OnDisappearing()
{
base.OnDisappearing();
Console.WriteLine("Disappeared");
qController.Kill();
}
protected override void OnAppearing()
{
base.OnAppearing();
Console.WriteLine("Appeared");
}
}
}
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:qController" x:Class="qController.qControllerPage">
<StackLayout x:Name="sLayout">
<Grid x:Name="topBar" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image x:Name = "scanButton" HorizontalOptions = "Start" Margin="20,10,20,10" Grid.Row="0" Grid.Column="0" />
<Image x:Name = "addButton" HorizontalOptions = "End" Margin="20,10,20,10" Grid.Row="0" Grid.Column="1" />
</Grid>
<ListView x:Name="lstView" HasUnevenRows = "true" >
</ListView>
</StackLayout>
</ContentPage>
@@ -0,0 +1,134 @@
using Xamarin.Forms;
using System.Net;
using System;
using Rug.Osc;
using Acr.UserDialogs;
using Acr.Settings;
using Zeroconf;
using System.Collections.Generic;
namespace qController
{
public partial class qControllerPage : ContentPage
{
public qControllerPage()
{
InitializeComponent();
InitGUI();
}
private void InitGUI()
{
NavigationPage.SetHasNavigationBar(this, false);
lstView.ItemsSource = QStorage.qInstances;
lstView.ItemTemplate = new DataTemplate(typeof(QInstanceCell));
lstView.SeparatorVisibility = SeparatorVisibility.None;
lstView.ItemTapped += (object sender, ItemTappedEventArgs e) =>
{
// don't do anything if we just de-selected the row
if (e.Item == null) return;
// do something with e.SelectedItem
((ListView)sender).SelectedItem = null; // de-select the row
};
topBar.BackgroundColor = Color.FromHex("71AEFF");
switch (Device.RuntimePlatform)
{
case Device.iOS:
scanButton.Margin = new Thickness(20, 45, 20, 10);
addButton.Margin = new Thickness(20, 45, 20, 10);
break;
}
addButton.Source = ImageSource.FromFile("add");
scanButton.Source = ImageSource.FromFile("scan");
lstView.BackgroundColor = Color.FromHex("4A4A4A");
BackgroundColor = Color.FromHex("4A4A4A");
var scanButtonGesture = new TapGestureRecognizer();
scanButtonGesture.Tapped += Scan;
scanButton.GestureRecognizers.Add(scanButtonGesture);
var addButtonGesture = new TapGestureRecognizer();
addButtonGesture.Tapped += AddWorkspace;
addButton.GestureRecognizers.Add(addButtonGesture);
}
void AddWorkspace(object sender, EventArgs e){
UserDialogs.Instance.Prompt(new PromptConfig
{
Title = "Enter IP of QLab Computer",
Message = "Enter an IP Address to save",
OkText = "Next",
OnTextChanged = args =>
{
//IPAddress ugh
args.IsValid = IPHelper.IsValidAddress(args.Value);
},
OnAction = (qAddress) =>
{
if (!qAddress.Ok)
return;
UserDialogs.Instance.Prompt(new PromptConfig
{
Title="Enter Name",
Message = "Enter a Name for " + qAddress.Text,
OkText="Save",
OnAction = (qName) => {
if (!qName.Ok)
return;
QStorage.AddInstance(qName.Text,qAddress.Text);
showToast("Manual Workspace Added!");
}
});
}
});
}
void showToast(string message){
var toastConfig = new ToastConfig(message);
toastConfig.SetDuration(3000);
toastConfig.SetPosition(ToastPosition.Bottom);
UserDialogs.Instance.Toast(toastConfig);
}
async void Scan(object sender, EventArgs e){
bool workspacesFound = false;
showToast("Scanning for Workspaces...");
Console.WriteLine("Begin Scanning");
IReadOnlyList<IZeroconfHost> results = await ZeroconfResolver.ResolveAsync("_qlab._udp.local.",TimeSpan.FromSeconds(3));
if(results != null){
foreach (var result in results)
{
if (result != null)
{
QStorage.AddInstance(result.DisplayName, result.IPAddress);
Console.WriteLine(result.DisplayName + " @ " + result.IPAddress + " added");
workspacesFound = true;
}
}
}
if(workspacesFound){
showToast("Workspace Found and Added!");
}else{
showToast("No Workspaces Found!");
}
}
}
}
+86
View File
@@ -0,0 +1,86 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Remove="MyPage.cs" />
<Compile Remove="Bespoke.Osc\Bespoke.Common.Osc\Properties\AssemblyInfo.cs" />
<Compile Remove="Bespoke.Osc\Samples\CS\Receiver\Program.cs" />
<Compile Remove="Bespoke.Osc\Samples\CS\Receiver\Properties\AssemblyInfo.cs" />
<Compile Remove="Bespoke.Osc\Samples\CS\Transmitter\ITransmitter.cs" />
<Compile Remove="Bespoke.Osc\Samples\CS\Transmitter\MulticastTransmitter.cs" />
<Compile Remove="Bespoke.Osc\Samples\CS\Transmitter\Program.cs" />
<Compile Remove="Bespoke.Osc\Samples\CS\Transmitter\TcpTransmitter.cs" />
<Compile Remove="Bespoke.Osc\Samples\CS\Transmitter\UdpTransmitter.cs" />
<Compile Remove="Bespoke.Osc\Samples\CS\Transmitter\Properties\AssemblyInfo.cs" />
<Compile Remove="Bespoke.Net\Assert.cs" />
<Compile Remove="Bespoke.Net\CommandLineParser.cs" />
<Compile Remove="Bespoke.Net\ExceptionEventArgs.cs" />
<Compile Remove="Bespoke.Net\FloatExtensions.cs" />
<Compile Remove="Bespoke.Net\InputManager.cs" />
<Compile Remove="Bespoke.Net\Node.cs" />
<Compile Remove="Bespoke.Net\ObjectRegistry.cs" />
<Compile Remove="Bespoke.Net\RandomHelper.cs" />
<Compile Remove="Bespoke.Net\ServiceContainer.cs" />
<Compile Remove="Bespoke.Net\StringExtensions.cs" />
<Compile Remove="Bespoke.Net\Net\IPServer.cs" />
<Compile Remove="Bespoke.Net\Net\TcpConnection.cs" />
<Compile Remove="Bespoke.Net\Net\TcpConnectionEventArgs.cs" />
<Compile Remove="Bespoke.Net\Net\TcpDataReceivedEventArgs.cs" />
<Compile Remove="Bespoke.Net\Net\TcpServer.cs" />
<Compile Remove="Bespoke.Net\Net\TransmissionType.cs" />
<Compile Remove="Bespoke.Net\Net\UdpDataReceivedEventArgs.cs" />
<Compile Remove="Bespoke.Net\Net\UdpServer.cs" />
<Compile Remove="Bespoke.Net\Properties\AssemblyInfo.cs" />
<Compile Remove="Classes\QButton.cs" />
</ItemGroup>
<ItemGroup>
<Compile Update="App.xaml.cs">
<DependentUpon>*.xaml</DependentUpon>
</Compile>
<Compile Condition=" '$(EnableDefaultCompileItems)' == 'true' " Update="Pages\ControlPage.xaml.cs">
<DependentUpon>*.xaml</DependentUpon>
</Compile>
<Compile Condition=" '$(EnableDefaultCompileItems)' == 'true' " Update="Pages\qControllerPage.xaml.cs">
<DependentUpon>*.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Rug.Osc" Version="1.2.5" />
<PackageReference Include="Acr.UserDialogs" Version="7.0.1" />
<PackageReference Include="Zeroconf" Version="2.9.0" />
<PackageReference Include="Xamarin.Forms" Version="3.0.0.482510" />
<PackageReference Include="Acr.Settings" Version="9.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="Rssdp" Version="4.0.2" />
</ItemGroup>
<ItemGroup>
<None Remove="App.xaml" />
<None Remove="qControllerPage.xaml" />
<None Remove="ControlPage.xaml" />
<None Remove="Bespoke.Osc\Samples\CS\Receiver\App.config" />
<None Remove="Bespoke.Osc\Samples\CS\Transmitter\App.config" />
<None Remove="Bespoke.Osc\Samples\VB\Receiver\App.config" />
<None Remove="Bespoke.Osc\Samples\VB\Receiver\My Project\Application.Designer.vb" />
<None Remove="Bespoke.Osc\Samples\VB\Receiver\My Project\Application.myapp" />
<None Remove="Bespoke.Net\.gitignore" />
<None Remove="Bespoke.Net\Help\Bespoke Common Library.chm" />
</ItemGroup>
<!--<ItemGroup>
<EmbeddedResource Include="Pages\ControlPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="Pages\qControllerPage.xaml" />
<EmbeddedResource Include="App.xaml" />
</ItemGroup>-->
<ItemGroup>
<Folder Include="Classes\" />
<Folder Include="Pages\" />
<Folder Include="Classes\Cues\" />
<Folder Include="Classes\Cell\" />
<Folder Include="Classes\Communication\" />
<Folder Include="Classes\Settings\" />
</ItemGroup>
</Project>