+ if (!SuppressUpdates && ActiveProcess == null)
+ {
+ SetControlsEnabled(false);
+ ActiveProcess = new UpdateConfiguration(ref Lib, Config);
+ ActiveProcess.EventHandler += ProcessEventHandler;
+ (new Thread(ActiveProcess.Run)).Start();
+ }
+ }
+
+ public void SendImageViewOn(CecLogicalAddress address)
+ {
+ if (!SuppressUpdates && ActiveProcess == null)
+ {
+ SetControlsEnabled(false);
+ ActiveProcess = new SendImageViewOn(ref Lib, address);
+ ActiveProcess.EventHandler += ProcessEventHandler;
+ (new Thread(ActiveProcess.Run)).Start();
+ }
+ }
+
+ public void ActivateSource(CecLogicalAddress address)
+ {
+ if (!SuppressUpdates && ActiveProcess == null)
+ {
+ SetControlsEnabled(false);
+ ActiveProcess = new SendActivateSource(ref Lib, address);
+ ActiveProcess.EventHandler += ProcessEventHandler;
+ (new Thread(ActiveProcess.Run)).Start();
+ }
+ }
+
+ public void SendStandby(CecLogicalAddress address)
+ {
+ if (!SuppressUpdates && ActiveProcess == null)
+ {
+ SetControlsEnabled(false);
+ ActiveProcess = new SendStandby(ref Lib, address);
+ ActiveProcess.EventHandler += ProcessEventHandler;
+ (new Thread(ActiveProcess.Run)).Start();
+ }
+ }
+
+ public void ShowDeviceInfo(CecLogicalAddress address)
+ {
+ if (!SuppressUpdates && ActiveProcess == null)
+ {
+ SetControlsEnabled(false);
+ ActiveProcess = new ShowDeviceInfo(this, ref Lib, address);
+ ActiveProcess.EventHandler += ProcessEventHandler;
+ (new Thread(ActiveProcess.Run)).Start();
+ }
+ }
+ #endregion
+
+ #region Configuration tab
+ private void cbOverrideAddress_CheckedChanged(object sender, EventArgs e)
+ {
+ SetControlEnabled(tbPhysicalAddress, ((CheckBox)sender).Checked);
+ SetControlEnabled(cbPortNumber, !((CheckBox)sender).Checked);
+ SetControlEnabled(cbConnectedDevice, !((CheckBox)sender).Checked && cbConnectedDevice.Items.Count > 1);
+ }
+
+ private void tbPhysicalAddress_TextChanged(object sender, EventArgs e)
+ {
+ if (tbPhysicalAddress.Text.Length != 4 ||
+ cbOverrideAddress.Checked)
+ return;
+ ushort physicalAddress = 0;
+ if (!ushort.TryParse(tbPhysicalAddress.Text, NumberStyles.AllowHexSpecifier, null, out physicalAddress))
+ return;
+
+ SetPhysicalAddress(physicalAddress);
+ }
+
+ private void UpdateSelectedDevice()
+ {
+ if (HasAVRDevice)
+ SetComboBoxItems(cbConnectedDevice, Config.BaseDevice == CecLogicalAddress.AudioSystem ? AVRVendorString : TVVendorString, new object[] { TVVendorString, AVRVendorString });
+ else
+ SetComboBoxItems(cbConnectedDevice, TVVendorString, new object[] { TVVendorString });
+ }
+
+ public void SetConnectedDevice(CecLogicalAddress address, int portnumber)
+ {
+ if (!SuppressUpdates && ActiveProcess == null)
+ {
+ SetControlsEnabled(false);
+ ActiveProcess = new UpdateConnectedDevice(ref Lib, address, portnumber);
+ ActiveProcess.EventHandler += ProcessEventHandler;
+ (new Thread(ActiveProcess.Run)).Start();
+ }
+ }
+
+ private void connectedDevice_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ SetConnectedDevice(SelectedConnectedDevice, SelectedPortNumber);
+ }
+
+ private void bCancel_Click(object sender, EventArgs e)
+ {
+ Dispose();
+ }
+
+ private void bSave_Click(object sender, EventArgs e)
+ {
+ SetControlsEnabled(false);
+
+ Config.UseTVMenuLanguage = cbUseTVMenuLanguage.Checked;
+ Config.ActivateSource = cbActivateSource.Checked;
+ Config.PowerOffScreensaver = cbPowerOffScreensaver.Checked;
+ Config.PowerOffOnStandby = cbPowerOffOnStandby.Checked;
+ Config.SendInactiveSource = cbSendInactiveSource.Checked;
+ Config.WakeDevices = WakeDevices;
+ Config.PowerOffDevices = PowerOffDevices;
+
+ /* save settings in the eeprom */
+ Lib.PersistConfiguration(Config);
+
+ /* and in xml */
+ if (ActiveProcess == null)
+ {
+ SetControlsEnabled(false);
+ string xbmcDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\XBMC\userdata\peripheral_data";
+ string defaultDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+
+ SaveFileDialog dialog = new SaveFileDialog()
+ {
+ Title = "Where do you want to store the settings?",
+ InitialDirectory = Directory.Exists(xbmcDir) ? xbmcDir : defaultDir,
+ FileName = "usb_2548_1001.xml",
+ Filter = "xml files (*.xml)|*.xml|All files (*.*)|*.*",
+ FilterIndex = 1
+ };
+
+ if (dialog.ShowDialog() == DialogResult.OK)
+ {
+ FileStream fs = null;
+ string error = string.Empty;
+ try
+ {
+ fs = (FileStream)dialog.OpenFile();
+ }
+ catch (Exception ex)
+ {
+ error = ex.Message;
+ }
+ if (fs == null)
+ {
+ MessageBox.Show("Cannot open '" + dialog.FileName + "' for writing" + (error.Length > 0 ? ": " + error : string.Empty ), "Pulse-Eight USB-CEC Adapter", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ else
+ {
+ StreamWriter writer = new StreamWriter(fs);
+ StringBuilder output = new StringBuilder();
+ output.AppendLine("<settings>");
+ output.AppendLine("<setting id=\"cec_hdmi_port\" value=\"" + Config.HDMIPort + "\" />");
+ output.AppendLine("<setting id=\"connected_device\" value=\"" + (Config.BaseDevice == CecLogicalAddress.AudioSystem ? 5 : 0) + "\" />");
+ output.AppendLine("<setting id=\"cec_power_on_startup\" value=\"" + (Config.ActivateSource ? 1 : 0) + "\" />");
+ output.AppendLine("<setting id=\"cec_power_off_shutdown\" value=\"" + (Config.PowerOffDevices.IsSet(CecLogicalAddress.Broadcast) ? 1 : 0) + "\" />");
+ output.AppendLine("<setting id=\"cec_standby_screensaver\" value=\"" + (Config.PowerOffScreensaver ? 1 : 0) + "\" />");
+ output.AppendLine("<setting id=\"standby_pc_on_tv_standby\" value=\"" + (Config.PowerOffOnStandby ? 1 : 0) + "\" />");
+ output.AppendLine("<setting id=\"use_tv_menu_language\" value=\"" + (Config.UseTVMenuLanguage ? 1 : 0) + "\" />");
+ output.AppendLine("<setting id=\"enabled\" value=\"1\" />");
+ output.AppendLine("<setting id=\"port\" value=\"\" />");
+
+ // only supported by 1.5.0+ clients
+ output.AppendLine("<!-- the following lines are only supported by v1.5.0+ clients -->");
+ output.AppendLine("<setting id=\"activate_source\" value=\"" + (Config.ActivateSource ? 1 : 0) + "\" />");
+ output.AppendLine("<setting id=\"physical_address\" value=\"" + string.Format("{0,4:X}", cbOverrideAddress.Checked ? Config.PhysicalAddress : 0).Trim() + "\" />");
+ output.AppendLine("<setting id=\"device_type\" value=\"" + (int)Config.DeviceTypes.Types[0] + "\" />");
+ output.AppendLine("<setting id=\"tv_vendor\" value=\"" + string.Format("{0,6:X}", (int)Config.TvVendor).Trim() + "\" />");
+
+ output.Append("<setting id=\"wake_devices\" value=\"");
+ StringBuilder strWakeDevices = new StringBuilder();
+ foreach (CecLogicalAddress addr in Config.WakeDevices.Addresses)
+ if (addr != CecLogicalAddress.Unknown)
+ strWakeDevices.Append(" " + (int)addr);
+ output.Append(strWakeDevices.ToString().Trim());
+ output.AppendLine("\" />");
+
+ output.Append("<setting id=\"standby_devices\" value=\"");
+ StringBuilder strSleepDevices = new StringBuilder();
+ foreach (CecLogicalAddress addr in Config.PowerOffDevices.Addresses)
+ if (addr != CecLogicalAddress.Unknown)
+ strSleepDevices.Append(" " + (int)addr);
+ output.Append(strSleepDevices.ToString().Trim());
+ output.AppendLine("\" />");
+
+ // only supported by 1.5.1+ clients
+ output.AppendLine("<!-- the following lines are only supported by v1.5.1+ clients -->");
+ output.AppendLine("<setting id=\"send_inactive_source\" value=\"" + (Config.SendInactiveSource ? 1 : 0) + "\" />");
+
+ output.AppendLine("</settings>");
+ writer.Write(output.ToString());
+ writer.Close();
+ fs.Close();
+ fs.Dispose();
+ MessageBox.Show("Settings are stored.", "Pulse-Eight USB-CEC Adapter", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+ }
+ SetControlsEnabled(true);
+ }
+ }
+
+ private void bReloadConfig_Click(object sender, EventArgs e)
+ {
+ if (Lib.CanPersistConfiguration())
+ {
+ Lib.GetCurrentConfiguration(Config);
+ ConfigurationChanged(Config);
+ }
+ else
+ {
+ ReloadXmlConfiguration();
+ }
+ }
+
+ private void cbVendorOverride_CheckedChanged(object sender, EventArgs e)
+ {
+ if (cbVendorOverride.Checked)
+ {
+ cbVendorId.Enabled = true;
+ switch (cbVendorId.Text)
+ {
+ case "LG":
+ Config.TvVendor = CecVendorId.LG;
+ break;
+ case "Onkyo":
+ Config.TvVendor = CecVendorId.Onkyo;
+ break;
+ case "Panasonic":
+ Config.TvVendor = CecVendorId.Panasonic;
+ break;
+ case "Philips":
+ Config.TvVendor = CecVendorId.Philips;
+ break;
+ case "Pioneer":
+ Config.TvVendor = CecVendorId.Pioneer;
+ break;
+ case "Samsung":
+ Config.TvVendor = CecVendorId.Samsung;
+ break;
+ case "Sony":
+ Config.TvVendor = CecVendorId.Sony;
+ break;
+ case "Yamaha":
+ Config.TvVendor = CecVendorId.Yamaha;
+ break;
+ default:
+ Config.TvVendor = CecVendorId.Unknown;
+ break;
+ }
+ }
+ else
+ {
+ cbVendorId.Enabled = false;
+ Config.TvVendor = CecVendorId.Unknown;
+ }
+ }
+
+ private void cbDeviceType_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ CecDeviceType type = SelectedDeviceType;
+ if (type != Config.DeviceTypes.Types[0])
+ {
+ Config.DeviceTypes.Types[0] = type;
+ if (!DeviceChangeWarningDisplayed)
+ {
+ DeviceChangeWarningDisplayed = true;
+ MessageBox.Show("You have changed the device type. Save the configuration, and restart the application to use the new setting.", "Pulse-Eight USB-CEC Adapter", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ }
+ }
+ }
+ #endregion
+
+ #region Key configuration tab
+ delegate void SelectKeypressRowCallback(CecKeypress key);
+ private void SelectKeypressRow(CecKeypress key)
+ {
+ if (dgButtons.InvokeRequired)
+ {
+ SelectKeypressRowCallback d = SelectKeypressRow;
+ try
+ {
+ Invoke(d, new object[] { key });
+ }
+ catch (Exception) { }
+ }
+ else
+ {
+ int rowIndex = -1;
+ foreach (DataGridViewRow row in dgButtons.Rows)
+ {
+ CecButtonConfigItem item = row.DataBoundItem as CecButtonConfigItem;
+ if (item != null && item.Key.Keycode == key.Keycode)
+ {
+ rowIndex = row.Index;
+ row.Selected = true;
+ item.Enabled = true;
+ }
+ else
+ {
+ row.Selected = false;
+ }
+ }
+ if (rowIndex > -1)
+ dgButtons.FirstDisplayedScrollingRowIndex = rowIndex;
+ }
+ }
+
+ private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
+ {
+ DataGridView grid = sender as DataGridView;
+ CecButtonConfigItem data = grid.Rows[e.RowIndex].DataBoundItem as CecButtonConfigItem;
+ if (data == null || !data.Enabled)
+ e.CellStyle.ForeColor = Color.Gray;
+ }
+ #endregion
+
+ #region CEC Tester tab
+ public void CheckActiveDevices()
+ {
+ CecLogicalAddresses activeDevices = Lib.GetActiveDevices();
+ List<string> deviceList = new List<string>();
+ foreach (CecLogicalAddress activeDevice in activeDevices.Addresses)
+ {
+ if (activeDevice != CecLogicalAddress.Unknown)
+ deviceList.Add(string.Format("{0,1:X} : {1}", (int)activeDevice, Lib.ToString(activeDevice)));
+ }
+ deviceList.Add(string.Format("{0,1:X} : {1}", (int)CecLogicalAddress.Broadcast, Lib.ToString(CecLogicalAddress.Broadcast)));
+
+ SetActiveDevices(deviceList.ToArray());
+ }
+
+ delegate void SetActiveDevicesCallback(string[] activeDevices);
+ private void SetActiveDevices(string[] activeDevices)
+ {
+ if (cbCommandDestination.InvokeRequired)
+ {
+ SetActiveDevicesCallback d = SetActiveDevices;
+ try
+ {
+ Invoke(d, new object[] { activeDevices });
+ }
+ catch (Exception) { }
+ }
+ else
+ {
+ cbCommandDestination.Items.Clear();
+ foreach (string item in activeDevices)
+ cbCommandDestination.Items.Add(item);
+ }
+ }
+
+ delegate CecLogicalAddress GetTargetDeviceCallback();
+ private CecLogicalAddress GetTargetDevice()
+ {
+ if (cbCommandDestination.InvokeRequired)
+ {
+ GetTargetDeviceCallback d = GetTargetDevice;
+ CecLogicalAddress retval = CecLogicalAddress.Unknown;
+ try
+ {
+ retval = (CecLogicalAddress)Invoke(d, new object[] { });
+ }
+ catch (Exception) { }
+ return retval;
+ }
+
+ return GetLogicalAddressFromString(cbCommandDestination.Text);
+ }
+
+ private CecLogicalAddress GetLogicalAddressFromString(string name)
+ {
+ switch (name.Substring(0, 1).ToLower())
+ {
+ case "0":
+ return CecLogicalAddress.Tv;
+ case "1":
+ return CecLogicalAddress.RecordingDevice1;
+ case "2":
+ return CecLogicalAddress.RecordingDevice2;
+ case "3":
+ return CecLogicalAddress.Tuner1;
+ case "4":
+ return CecLogicalAddress.PlaybackDevice1;
+ case "5":
+ return CecLogicalAddress.AudioSystem;
+ case "6":
+ return CecLogicalAddress.Tuner2;
+ case "7":
+ return CecLogicalAddress.Tuner3;
+ case "8":
+ return CecLogicalAddress.PlaybackDevice2;
+ case "9":
+ return CecLogicalAddress.RecordingDevice3;
+ case "a":
+ return CecLogicalAddress.Tuner4;
+ case "b":
+ return CecLogicalAddress.PlaybackDevice3;
+ case "c":
+ return CecLogicalAddress.Reserved1;
+ case "d":
+ return CecLogicalAddress.Reserved2;
+ case "e":
+ return CecLogicalAddress.FreeUse;
+ case "f":
+ return CecLogicalAddress.Broadcast;
+ default:
+ return CecLogicalAddress.Unknown;
+ }
+ }
+
+ private void bSendImageViewOn_Click(object sender, EventArgs e)
+ {
+ SendImageViewOn(GetTargetDevice());
+ }
+
+ private void bStandby_Click(object sender, EventArgs e)
+ {
+ SendStandby(GetTargetDevice());
+ }
+
+ private void bScan_Click(object sender, EventArgs e)
+ {
+ ShowDeviceInfo(GetTargetDevice());
+ }
+
+ private void bActivateSource_Click(object sender, EventArgs e)
+ {
+ ActivateSource(GetTargetDevice());
+ }
+
+ private void cbCommandDestination_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ bool enableVolumeButtons = (GetTargetDevice() == CecLogicalAddress.AudioSystem);
+ bVolUp.Enabled = enableVolumeButtons;
+ bVolDown.Enabled = enableVolumeButtons;
+ bMute.Enabled = enableVolumeButtons;
+ bActivateSource.Enabled = (GetTargetDevice() != CecLogicalAddress.Broadcast);
+ bScan.Enabled = (GetTargetDevice() != CecLogicalAddress.Broadcast);
+ }
+
+ private void bVolUp_Click(object sender, EventArgs e)
+ {
+ SetControlsEnabled(false);
+ Lib.VolumeUp(true);
+ SetControlsEnabled(true);
+ }
+
+ private void bVolDown_Click(object sender, EventArgs e)
+ {
+ SetControlsEnabled(false);
+ Lib.VolumeDown(true);
+ SetControlsEnabled(true);
+ }
+
+ private void bMute_Click(object sender, EventArgs e)
+ {
+ SetControlsEnabled(false);
+ Lib.MuteAudio(true);
+ SetControlsEnabled(true);
+ }
+
+ private void bRescanDevices_Click(object sender, EventArgs e)
+ {
+ if (!SuppressUpdates && ActiveProcess == null)
+ {
+ SetControlsEnabled(false);
+ ActiveProcess = new RescanDevices(ref Lib);
+ ActiveProcess.EventHandler += ProcessEventHandler;
+ (new Thread(ActiveProcess.Run)).Start();
+ }
+ }
+ #endregion
+
+ #region Log tab
+ delegate void UpdateLogCallback();
+ private void UpdateLog()
+ {
+ if (tbLog.InvokeRequired)
+ {
+ UpdateLogCallback d = UpdateLog;
+ try
+ {
+ Invoke(d, new object[] { });
+ }
+ catch (Exception) { }
+ }
+ else
+ {
+ tbLog.Text = Log;
+ tbLog.Select(tbLog.Text.Length, 0);
+ tbLog.ScrollToCaret();
+ }
+ }
+
+ private void AddLogMessage(CecLogMessage message)
+ {
+ string strLevel = "";
+ bool display = false;
+ switch (message.Level)
+ {
+ case CecLogLevel.Error:
+ strLevel = "ERROR: ";
+ display = cbLogError.Checked;
+ break;
+ case CecLogLevel.Warning:
+ strLevel = "WARNING: ";
+ display = cbLogWarning.Checked;
+ break;
+ case CecLogLevel.Notice:
+ strLevel = "NOTICE: ";
+ display = cbLogNotice.Checked;
+ break;
+ case CecLogLevel.Traffic:
+ strLevel = "TRAFFIC: ";
+ display = cbLogTraffic.Checked;
+ break;
+ case CecLogLevel.Debug:
+ strLevel = "DEBUG: ";
+ display = cbLogDebug.Checked;
+ break;
+ default:
+ break;
+ }
+
+ if (display)
+ {
+ string strLog = string.Format("{0} {1,16} {2}", strLevel, message.Time, message.Message) + System.Environment.NewLine;
+ Log += strLog;
+ }
+
+ if (SelectedTab == ConfigTab.Log)
+ UpdateLog();
+ }
+
+ private void bClearLog_Click(object sender, EventArgs e)
+ {
+ Log = string.Empty;
+ UpdateLog();
+ }