Program closing thread when button pressed Raspberry Pi - multithreading

I realize there are similar questions here and I have looked at them, I just can't apply the solutions to my own problem.
I am writing an MP3 player for a Pi using visual studio (C#) on a PC, then using Mono on the Pi to run it.
As Mono does not seem to have an MP3 library (happy to be corrected) my workaround is to use a gui interface to control a command line mp3 player (omxplayer).
I have a working test interface which i ssh across to the Pi from my PC to test each time.
The problem is when I hit Button1 to run it, it works fine in that the mp3 plays.
But as soon as I hit button 2 to send the app the "p" key which should pause the program, it just quit out. Ultimately I will have a bunch of buttons sending key presses to control it like next skip stop etc.
I have tested the functionality from a terminal and it works fine.
Any suggestions would be appreciated.
Here is my code.
"Oh", Please don't flame me for making procStartInfo and proc global, I was grasping at straws :)
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
ProcessStartInfo procStartInfo;
System.Diagnostics.Process proc;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "Button Clicked";
procStartInfo = new ProcessStartInfo("omxplayer", "/home/pi/Music/Debug/Mutter.mp3 &");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
}
private void button2_Click(object sender, EventArgs e)
{
Close();
}
private void button3_Click(object sender, EventArgs e)
{
SendKeys.Send("{p}");
}
}
}

Related

Video frame rate is too slow from IP Camera using Aforge Jpegstream C#

I'm using Aforge library to try to get a live stream from an IP Camera. My problem is, Frame rate is too slow and about one frame every 3 or 4 seconds! I have connected my camera directly to my computer through LAN port.
Here is my code :
JPEGStream stream;
public Form1()
{
InitializeComponent();
stream = new JPEGStream("http://192.168.1.88/pda.cgi?user=myusername&password=mypass&page=image&cam=1");
stream.NewFrame += stream_NewFrame;
}
private void stream_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap bmp =(Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = bmp;
}
private void button5_Click_1(object sender, EventArgs e)
{
stream.Start();
}
private void button9_Click(object sender, EventArgs e)
{
stream.Stop();
}
I don't know if it will count as an answer but, have you tried to edit the FrameInterval Property of the JPEGStream?.
Set that to 0 so you can get as many as frame as possible
stream.FrameInterval = 0;
But I'll suggest use the MJPEGStream instead of JPEGStream if your IP Cam is supporting it. It is faster than the JPEGStream

How can I override or act on KeyDown: Space or Enter for ListView in UWP?

I've attached the KeyDown event to a ListView in my Win 10 UWP app. I want to make VirtualKey.Enter have a special effect, but the event is not firing for this particular key. Neither does it for Space, Arrow up or down. This I guess because the listview already has defined a special behaviour for those keys.
I'd like to override some of those keys though, or at least trigger additional actions. Even attaching events to those key with modifiers (e.g. Shift+ArrowDown) would not work because the events still are not firing.
I read that for WPF that there is a PreviewKeyDown-event which one can attach to. I can't find that event for UWP though. Are there any other options?
Stephanie's answer is a good one and it works in the general case. However, as Nilzor observed it will not work in the case of a ListView for the Enter key. For some reason the ListView handles the KeyDown event in case Enter is pressed.
A better way to handle key events when dealing with a ListView, as the question asks, is this.
private void ListView_Loaded(object sender, RoutedEventArgs e)
{
(sender as ListView).AddHandler(UIElement.KeyDownEvent, new KeyEventHandler(ListView_KeyDown), true);
}
private void ListView_KeyDown(object sender, KeyRoutedEventArgs args)
{
if (args.Key == Windows.System.VirtualKey.Enter)
{
}
}
Notice the last argument in the AddHandler function. This specifies whether we want to handle events already handled by a previous element in the visual tree.
Of course don't forget to unsubscribe from the event when appropriate
Here is one way to do it : subscribe to the global Window.Current.CoreWindow.KeyDown event.
Then save the focus state of your listview and react accordingly.
Here is the code :
public sealed partial class MainPage : Page
{
bool hasFocus = false;
public MainPage()
{
this.InitializeComponent();
Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown;
}
private void CoreWindow_KeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args)
{
if(hasFocus)
{
Debug.Write("Key down on list");
}
}
private void myList_GotFocus(object sender, RoutedEventArgs e)
{
hasFocus = true;
}
private void myList_LostFocus(object sender, RoutedEventArgs e)
{
hasFocus = false;
}
You will also need to subscribe to the focus events in xaml, for your ListView :
<ListView .... GotFocus="myList_GotFocus" LostFocus="myList_LostFocus"/>
Corcus's solution doesn't work for me. What is working is handling PreviewKeyDown directly from XAML. Works well for SPACE or ENTER key:
XAML:
<ListView PreviewKeyDown="BookmarksListView_PreviewKeyDown">
Code behind:
private void BookmarksListView_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
// DO YOUR STUFF...
e.Handled = true;
}
}
You can use AddHandler method.
private void KeyEnterEventHandler(object sender, KeyRoutedEventArgs e)
{
if (e.OriginalKey == Windows.System.VirtualKey.Enter)
{
PlayFromListView();
}
}
private void LoadListView()
{
foreach (var music in playListStorageFile.PlayList)
{
ListViewItem item = new ListViewItem();
item.AddHandler(FrameworkElement.KeyDownEvent, new KeyEventHandler(KeyEnterEventHandler), true);
TextBlock mytext = new TextBlock();
mytext.Text = music.Nro.ToString() + " - " + music.Name;
mytext.Tag = music.Nro;
item.Content = mytext;
lvMusics.Items.Add(item);
}
}
https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.uielement.addhandler?view=winrt-18362

c# showing error while browsing a webpage

This is a test program. I just created a simple Windows application form with one button, and if the button is clicked, I need it to do something. So, I wrote my code as:
IWebDriver driver;
public Form1()
{
InitializeComponent();
}
public void SetupTest()
{
driver = new FirefoxDriver();
}
private void button1_Click(object sender, EventArgs e)
{
driver.Navigate().GoToUrl("webaddress");
driver.FindElement(By.TagName("Atlast")).Click();
Thread.Sleep(5000);
}
I have included all of the dependencies (both code and references), but I am getting the following error when I click the button:
Object reference not set to an instance of an object. in driver.navigate part of my code..
What mistake did I make here? Can anyone please help me out with this?
private void button1_Click(object sender, EventArgs e)
{
SetupTest()
driver.Navigate().GoToUrl("webaddress");
driver.FindElement(By.TagName("Atlast")).Click();
Thread.Sleep(5000);
}
You need to be calling SetupTest in your button click code. Why? This is where you are creating your new instance of the IWebDriver, therefore it needs to be called otherwise any references to driver will simply refer to null (by default).

C# code fails to read serial input from Arduino

Hi I am trying to read serial input from my Arduino but I am having no luck. I believe I am opening and closing the connection correctly but do not appear to be having much success!
I'm sure the Arduino is outputting data because I can see it in the serial terminal.
The code for my C# program is below, I was wondering if anyone could spot any mistakes I may have missed.
Also this is an example of the serial data I should receive "12.2,1111,332,233"
namespace FridgeProtectionDeviceMonitor
{
public partial class Online_mode : Form
{
public Online_mode()
{
InitializeComponent();
}
private void Online_mode_Load(object sender, EventArgs e)
{
cmbPortSelection.DataSource = SerialPort.GetPortNames();
cmbChartSelection.SelectedIndex = 0;
}
string x = "";
SerialPort port;
private void btnFindPorts_Click(object sender, EventArgs e)
{
var ports = SerialPort.GetPortNames();
cmbPortSelection.DataSource = ports;
}
private void btnOpenPort_Click(object sender, EventArgs e)
{
if (cmbPortSelection.SelectedIndex > -1)
{
port = new SerialPort(cmbPortSelection.Text);
try
{
if (!port.IsOpen)
{
port.BaudRate = 9600;
port.Open();
}
}
catch (Exception)
{
MessageBox.Show("Serial connection request denied: Port is in use!");
}
}
else
{
MessageBox.Show("Serial connection request denied: No port selected!");
}
}
private void btnClosePort_Click(object sender, EventArgs ex)
{
try
{
port.Close();
}
catch (Exception)
{
MessageBox.Show("Serial close connection request denied: ", ex.ToString());
}
}
private void update(object sender, EventArgs e)
{
txtSaveLocation.Text = x;
}
private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
x = port.ReadLine().ToString();
MessageBox.Show(x);
this.Invoke(new EventHandler(update));
}
}
}
I was just working on the same thing as you, you'll have to modify it if you want to use it for your purposes, but here's the code I use that works. The only problem is that for me I need it to read very quickly because it's for a speedometer and it sort of lags (anyone know why?) but anyways here's my code that works for me.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void Form1_Load(object sender, EventArgs e)
{
try
{
if (arduinoCom.IsOpen == false)
{
arduinoCom.Open();
}
}
catch
{
MessageBox.Show("Serial Error: Is your serial plugged in?");
}
}
private void refresh_Tick(object sender, EventArgs e)
{
string speedReading = arduinoCom.ReadLine();
speed.Text = speedReading;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
arduinoCom.Close();
}
}
}
I've got a USB to serial converter linked to an XBee wireless bridge linked to PIC micro-controllers and i've found that running the serial port read functions in a separate thread increases communication speeds something chronic!
The readline blocks the code until the newline character is received, therefore blocking your main thread. Before i moved it to another thread my GUI became un-responsive etc.
By the way I'm using ReadByte().
I'm continuously reading bytes from the serial buffer in a backgroundworker and storing them in a thread safe queue. Then checking the queue for my communication start bits and analyzing the packet from there. Using manual reset events I'm syncing everything.
In my experience the port_datareceived event is a nice addition to the serialport class but unfortunately it is relatively useless for fast communications. I'm running at 12900 baud.
If you want code snippets i can provide them.
Regards,
Pete
P.S. I'm using an ATS5004D 4 channel differential oscilloscope with multichannel software. multichannel software can analyse the voltage signal into serial data through it's built in serial analyzer block. That way you can see what's actually being discussed on the serial comms lines!! cutting out all the BS other serial terminals add...
#michael b I'd start by looking at what the actual communication is doing i.e. scope the TX RX lines to see what the arduino board is putting out. I have only little experience with arduino but its predecessor the PICAXE system had a debug function which slowed everything down heaps, is something like this going on?
How many times per second do you want to update the speedo?
The SAE J1939 automotive serial communication standard says that RPM only needs to be updated once every 100ms. The human eye usually can't see/react faster than 300ms. 9600 baud gives you one 8bit byte per millisecond approx.
Personally I wouldn't use the timer to get the updates and instead do everything on a separate thread from main, and let it run as fast/slow as it wants.
this thread shows you roughly how i've set up my communications System.IO.IOException: A device attached to the system is not functioning C# .NET 4.0
hope it helps,
pete

creating a play / pause toggle switch

I am using silverlight 4 with smf and I want to create a play , pause toggle button. So if the media is playing and if the button is clicked it will pause the video. But if the media is paused, it will restart playing video.
How can I do that
private void btnPlay_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
}
I don't know anything about silverlight, but you could use a boolean.
private void btnPlay_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if(isPlaying)
{
music.pause();
isPlaying = FALSE;
return;
}
music.play();
isPlaying = TRUE;
return;
}

Resources