Continuously getting data from heart rate monitor - c#

I've been working on a project that reads a person's heart rate from a Polar H7 hrm. I've been successful in connecting the device and getting the heart rate which the program shows as text in the UI. However, there are instances where the program suddenly stops getting input from the device.
I have already checked the connection of the device to my Win 10 laptop and saw that it was stable, there were also no exceptions getting thrown by the program. The text simply stops changing.
Here is the code I've written:
public sealed partial class MainPage : Page
{
private GattDeviceService device;
public MainPage()
{
this.InitializeComponent();
init();
}
async void init()
{
var devices = await DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(GattServiceUuids.HeartRate));
Status.Text = devices.Count.ToString();
device = await GattDeviceService.FromIdAsync(devices[0].Id);
enableSensor();
}
private async void enableSensor()
{
IReadOnlyList<GattCharacteristic> characteristicList;
characteristicList = device.GetAllCharacteristics();
if (characteristicList != null)
{
GattCharacteristic characteristic = characteristicList[0];
if (characteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Notify))
{
characteristic.ValueChanged += SendNotif;
await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
}
}
}
async void SendNotif(GattCharacteristic sender, GattValueChangedEventArgs eventArgs)
{
if (eventArgs.CharacteristicValue.Length != 0) {
byte[] hrData = new byte[eventArgs.CharacteristicValue.Length];
DataReader.FromBuffer(eventArgs.CharacteristicValue).ReadBytes(hrData);
var hrValue = ProcessData(hrData);
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
Status.Text = hrValue.ToString();
});
}
}
private int ProcessData(byte[] data)
{
// Heart Rate profile defined flag values
const byte heartRateValueFormat = 0x01;
byte currentOffset = 0;
byte flags = data[currentOffset];
bool isHeartRateValueSizeLong = ((flags & heartRateValueFormat) != 0);
currentOffset++;
ushort heartRateMeasurementValue;
if (isHeartRateValueSizeLong)
{
heartRateMeasurementValue = (ushort)((data[currentOffset + 1] << 8) + data[currentOffset]);
currentOffset += 2;
}
else
{
heartRateMeasurementValue = data[currentOffset];
}
return heartRateMeasurementValue;
}
}

Related

SpeechSynthesizer inside for loop not iterating in unity

I am modifying the code from https://github.com/Azure-Samples/cognitive-services-speech-sdk/blob/master/quickstart/csharp/unity/text-to-speech/Assets/Scripts/HelloWorld.cs to make it count from 1 to 10. While the iteration is displayed fine in the console but the system only says "ten".
I am trying to make it say "one", "two", "three" .... "ten" using for loop.
What am I missing?
using UnityEngine;
using UnityEngine.UI;
using Microsoft.CognitiveServices.Speech;
using System.Threading.Tasks;
public class HelloWorld : MonoBehaviour
{
// Hook up the three properties below with a Text, InputField and Button object in your UI.
public Text outputText;
public InputField inputField;
public Button speakButton;
public AudioSource audioSource;
private object threadLocker = new object();
private bool waitingForSpeak;
private string message;
private SpeechConfig speechConfig;
private SpeechSynthesizer synthesizer;
public void ButtonClick()
{
// Starts speech synthesis, and returns after a single utterance is synthesized.
for (int j = 1; j <= 10; j++)
{
Debug.Log("Iteration: " + j);
using (var result = synthesizer.SpeakTextAsync(j.ToString()).Result)
{
// Checks result.
if (result.Reason == ResultReason.SynthesizingAudioCompleted)
{
var sampleCount = result.AudioData.Length / 2;
var audioData = new float[sampleCount];
for (var i = 0; i < sampleCount; ++i)
{
audioData[i] = (short)(result.AudioData[i * 2 + 1] << 8 | result.AudioData[i * 2]) / 32768.0F;
}
// The output audio format is 16K 16bit mono
var audioClip = AudioClip.Create("SynthesizedAudio", sampleCount, 1, 16000, false);
audioClip.SetData(audioData, 0);
audioSource.clip = audioClip;
audioSource.Play();
newMessage = "Speech synthesis succeeded!";
}
else if (result.Reason == ResultReason.Canceled)
{
var cancellation = SpeechSynthesisCancellationDetails.FromResult(result);
newMessage = $"CANCELED:\nReason=[{cancellation.Reason}]\nErrorDetails=[{cancellation.ErrorDetails}]\nDid you update the subscription info?";
}
}
}
}
void Start()
{
if (outputText == null)
{
UnityEngine.Debug.LogError("outputText property is null! Assign a UI Text element to it.");
}
else if (inputField == null)
{
message = "inputField property is null! Assign a UI InputField element to it.";
UnityEngine.Debug.LogError(message);
}
else if (speakButton == null)
{
message = "speakButton property is null! Assign a UI Button to it.";
UnityEngine.Debug.LogError(message);
}
else
{
inputField.text = "Enter text you wish spoken here.";
message = "Click button to synthesize speech";
speakButton.onClick.AddListener(ButtonClick);
speechConfig = SpeechConfig.FromSubscription("YourSubscriptionKey", "northeurope");
// The default format is Riff16Khz16BitMonoPcm.
// We are playing the audio in memory as audio clip, which doesn't require riff header.
// So we need to set the format to Raw16Khz16BitMonoPcm.
speechConfig.SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Raw16Khz16BitMonoPcm);
// Creates a speech synthesizer.
// Make sure to dispose the synthesizer after use!
synthesizer = new SpeechSynthesizer(speechConfig, null);
}
}
void Update()
{
lock (threadLocker)
{
if (speakButton != null)
{
speakButton.interactable = !waitingForSpeak;
}
if (outputText != null)
{
outputText.text = message;
}
}
}
void OnDestroy()
{
synthesizer.Dispose();
}
}
I ended up doing the following and it's working as I wanted. Basically made the button click function to async and awaited for the synthesizer.
public async void ButtonClick()
{
Debug.Log("Button Pressed!");
for (int j = 1; j <= 10; j++)
{
string newMessage = string.Empty;
var config = SpeechConfig.FromSubscription("KEY", "northeurope");
using var synthesizer = new SpeechSynthesizer(config);
await synthesizer.SpeakTextAsync(j.ToString());
}
}

C# GeoLocation Watcher taking too long to get coordinates

I have created a Windows Form App for our works Windows Tablets (windows 10) to track location.
The class I have created is below:
class LocationServices
{
private GeoCoordinateWatcher myWatcher;
private bool fgWatcherStarted = false;
public LocationServices()
{
myWatcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
fgWatcherStarted = myWatcher.TryStart(true, System.TimeSpan.FromMilliseconds(1000));
}
public LatLon GetDeviceLocation()
{
LatLon myReturn = new LatLon();
System.Device.Location.GeoCoordinate myPosition = new System.Device.Location.GeoCoordinate();
try
{
if (!fgWatcherStarted)
{
fgWatcherStarted = myWatcher.TryStart(true, System.TimeSpan.FromMilliseconds(1000));
}
myPosition = myWatcher.Position.Location;
if (myPosition.IsUnknown)
{
myReturn.Latitude = 0;
myReturn.Longitude = 0;
myReturn.strMessage = "Unknown Position";
}
else
{
myReturn.Latitude = myPosition.Latitude;
myReturn.Longitude = myPosition.Longitude;
myReturn.strMessage = myPosition.Course.ToString();
}
}
catch (Exception ex)
{
myReturn.Latitude = 0;
myReturn.Longitude = 0;
myReturn.strMessage = ex.Message.ToString();
}
return myReturn;
}
}
In my code I am running through every few seconds and getting the location by calling the class above.
If I am connected to wifi (running from my desk) it gets the location instantly and works as expected, but from the device it returns 0 for a significant amount of time and then suddenly starts working and works perfectly fine with no issues.
Is there anything I can do to make this start quicker? I initially thought it could be the location/signal but I have tried loading in the same place and leaving it and once it initialises it works perfectly but it's the initial coordinates that take ages to load.
Looks as though there needs to be a position change for it to return a value, see the answer here: https://stackoverflow.com/a/52910209/6639187
Not quite sure about your way of getting the coordinates, I used to do the following method - hope this helps (run it in a console app and check as follows)
class Program
{
private static GeoCoordinateWatcher Watcher;
static void Main(string[] args)
{
Watcher = new GeoCoordinateWatcher();
Watcher.StatusChanged += Watcher_StatusChanged;
Watcher.Start();
Console.ReadLine();
}
static void Watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
if (e.Status == GeoPositionStatus.Ready)
{
if (Watcher.Position.Location.IsUnknown)
{
Console.Write("Cannot find location");
}
else
{
Console.WriteLine("Lat: " + Watcher.Position.Location.Latitude.ToString());
Console.WriteLine("Lon: " + Watcher.Position.Location.Longitude.ToString());
}
}
}
}

Check if multiple buttons are pushed Windows IoT with Raspberry PI 3B

I'm currently working with the Raspberry PI 3 with Windows 10 IoT and I'm trying to make the game 'Simon Says' in Visual Studio 2015.
Everything is plugged in as followed:
Fritzing image
I got the LEDs working but I can't really figure out how to detect when a button is being pressed.
Parts of the source code:
Variables
private const int BTNRED = 5;
private const int BTNBLUE = 6;
private const int BTNYELLOW = 13;
private const int BTNGREEN = 19;
private GpioPin _btnRed;
private GpioPin _btnBlue;
private GpioPin _btnYellow;
private GpioPin _btnGreen;
private Random rnd;
private static GpioController _gpioController;
Method to recognize when a button is being pressed.
public static IList<Step> PressedButtons
{
get
{
List<Step> returnVal = new List<Step>();
if (GetMap._btnBlue.Read() == GpioPinValue.High)
{ returnVal.Add(Step.Blue); }
if (GetMap._btnGreen.Read() == GpioPinValue.High)
{ returnVal.Add(Step.Green); }
if (GetMap._btnRed.Read() == GpioPinValue.High)
{ returnVal.Add(Step.Red); }
if (GetMap._btnYellow.Read() == GpioPinValue.High)
{ returnVal.Add(Step.Yellow); }
return returnVal;
}
}
/// <summary>
/// Checks if any of the 4 buttons is pressed.
/// </summary>
/// <returns>Returns false if no button is pressed.</returns>
public static bool isButtonPressed
{
get
{
if (GetMap._btnBlue.Read() == GpioPinValue.Low)
{ return true; }
if (GetMap._btnGreen.Read() == GpioPinValue.Low)
{ return true; }
if (GetMap._btnRed.Read() == GpioPinValue.Low)
{ return true; }
if (GetMap._btnYellow.Read() == GpioPinValue.Low)
{ return true; ; }
return false;
}
}
Assigning the right pins on the GPIO to the corresponding variables
private GPIOMap()
{
rnd = new Random();
_gpioController = GpioController.GetDefault();
if (_gpioController == null) { return; }
_ledRed = _gpioController.OpenPin(LEDRED);
_ledRed.SetDriveMode(GpioPinDriveMode.Output);
_ledYellow = _gpioController.OpenPin(LEDYELLOW);
_ledYellow.SetDriveMode(GpioPinDriveMode.Output);
_ledGreen = _gpioController.OpenPin(LEDGREEN);
_ledGreen.SetDriveMode(GpioPinDriveMode.Output);
_ledBlue = _gpioController.OpenPin(LEDBLUE);
_ledBlue.SetDriveMode(GpioPinDriveMode.Output);
_btnBlue = _gpioController.OpenPin(BTNBLUE);
_btnGreen = _gpioController.OpenPin(BTNGREEN);
_btnRed = _gpioController.OpenPin(BTNRED);
_btnYellow = _gpioController.OpenPin(BTNYELLOW);
}
private static GPIOMap GPIOMapInstance;
public static GPIOMap GetMap
{
get
{
if (GPIOMapInstance == null || _gpioController == null)
{ GPIOMapInstance = new GPIOMap(); }
return GPIOMapInstance;
}
}
Run game, where as you can see it should bring me to state 2 whenever a button is being pressed. However this isn't quite the case as the idle animation keeps on going on.
private void RunGame()
{
while (_isRunning)
{
switch (_state)
{
//Idle state
case (0x01):
//If any button is pressed, start the game.
if (GPIOMap.isButtonPressed)
{
_state = 0x02;
Task.Delay(500).Wait();
GPIOMap.PlayStartAnimation();
Task.Delay(1000).Wait();
break;
}
//If nothing happens, continue playing the idle animation.
GPIOMap.PlayIdleAnimationOnce();
break;
//Playback state
case (0x02):
//Play all the currently existing steps.
for (int i = 0; i <= _gameInstance.TotalSteps; i++)
{ GPIOMap.BlinkLight(_gameInstance.GetNextStep(), 500); }
//Generate and play a new step.
GPIOMap.BlinkLight(_gameInstance.GetNextStep(), 500);
//Switch to the input state.
_state = 0x03;
//Set the start time for the input.
_answerPending = DateTime.UtcNow;
break;
//Input state
case (0x03):
if(_gameInstance.CurrentStep > MAXSTEPS)
{
//Win Game
ResetGame();
break;
}
//If the player waits too long before answering, lose the game.
if ((DateTime.UtcNow - _answerPending) > _timeout)
{
GPIOMap.ConfirmWrongAnswer();
ResetGame();
break;
}
//If there are no more steps to re-trace, go back to playback state.
if (_gameInstance.CurrentStep > _gameInstance.TotalSteps)
{ _gameInstance.ResetSteps(); _state = 0x02; break; }
//If no buttons are pressed, keep polling.
if (!GPIOMap.isButtonPressed) { break; }
IList<Step> pressedButtons = GPIOMap.PressedButtons;
//If anything but one button is pressed, lose the game.
if (pressedButtons.Count != 1)
{
GPIOMap.ConfirmWrongAnswer();
ResetGame();
break;
}
if (_gameInstance.VerifyStep(pressedButtons[0]))
{
GPIOMap.BlinkLight(pressedButtons[0], 500);
}
else//Wrong step, end game
{
GPIOMap.ConfirmWrongAnswer();
ResetGame();
break;
}
break;
}
}
}
How can I get my source code to recognize when a button is being pressed so I can go to the next state which involves getting user input on the buttons.
You can use GPIO ValueChanged to catch the button pressed event like this:
_btnBlue = _gpioController.OpenPin(BTNBLUE);
_btnBlue.ValueChanged += btnValueChanged;
public void btnValueChanged(GpioPin pin, GpioPinValueChangedEventArgs e)
{
if (_btnBlue.Read() == GpioPinValue.Low)
{
isBlueButtonPressed = true;
}
}

Serial Port - reading data/updating canvas element

I've been having issues for a few weeks now reading in data from a serial port and updating a canvas element based on the message being received. The canvas element to be updated is a small image, that is supposed to rotate to a certain angle based on the third section of the message being received. I'm not sure what's going wrong, it seems that a full message isn't always being received. I'm going to give as much detail about the port and data.
Structure - 8 data bits, 1 start bit, 1 stop bit, no parity. Message frequency is 15 Hz (the number of lines written every second). The default baud rate is 9,600.
There are five sections:
1. Section1 - two decimal places.
2. Section2 - two decimal places.
3. Angle - multiplied by 10 – i.e. 256.0 degrees is shown as 2560.
4. Section4 multiplied by -100 – i.e. 6.66 degrees is -666.
5. Section5 multiplied by 100 – i.e. 55.5 degrees is 555.
A message starts with a colon symbol (:) and ends with < CR>< LF> . A field that contains asterisks, '***', indicates that no value is defined for that field.
An example to illustrate:
Column
1 15 22 29 36 43
1.00 *** 0 0 0
: 1.00 20.20 2460 0 0
: 2.40 20.45 2460 10000 -10000
: 3.00 20.45 2355 1000 554
I have the latest message received being shown at the top of the window to ensure the user that data is being received, but I noticed the message is only show bits and pieces of what it should be, and thus messing up the rotation of the canvas element. So for instance, the message might be : 20 500 at first, and then get a complete message.
Here's a screenshot of the data being sent:
Here's relative code in my MainWindow.cs:
private Port port = new Port();
private double rovHeading;
Point rotate_Origin = new Point(0.5, 0.5);
public string LastCOMMessage
{
get { return (string)this.GetValue(LastCoMMessageProperty); }
set { this.SetValue(LastCoMMessageProperty, value); }
}
private void Connect_Port(object sender, RoutedEventArgs e)
{
if (port.Status == Port.PortStatus.Disconnected)
{
try
{
port.Connect("COM1", 9600, false, 250); //When set to false, test data is used on Connect. Last parameter is how often the UI is updated. Closer to 0, the faster it updates.
//Sets button State and Creates function call on data recieved
Connect_btn.Content = "Disconnect";
port.OnMessageReceived += new Port.MessageReceivedHandler(port_OnMessageReceived);
}
catch (Exception)
{
System.Windows.MessageBox.Show("Port is not available.");
}
}
else
{
try // just in case serial port is not open, could also be achieved using if(serial.IsOpen)
{
port.Disconnect();
Connect_btn.Content = "Connect";
}
catch
{
}
}
}
/// <summary>
/// Reads in the data streaming from the port, taking out the third value which is the ROV's heading and assigning it to rovHeading.
/// It then calls orientRovImage.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void port_OnMessageReceived(object sender, Port.MessageEventArgs e)
{
LastCOMMessage = e.Message;
if (rovImage != null && e.Message.EndsWith("\r\n")) //messages end in <CR><LF>. Was having issues where only half a message would be received and updated the heading to wrong number.
{
string[] messageComponents = LastCOMMessage.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
if (messageComponents.Length >= 3)
{
double.TryParse(messageComponents[3], out rovHeading);
if (rovHeading > 0)
{
rovHeading /= 10;
orientRovImage();
}
}
}
}
/// <summary>
/// Rotates the ROV icon based on the heading being streamed in.
/// </summary>
private void orientRovImage()
{
RotateTransform rotateRov = new RotateTransform(rovHeading + angle_Offset);
rovImage.RenderTransformOrigin = rotate_Origin;
rovImage.RenderTransform = rotateRov;
}
Here's my Port.cs:
class Port
{
private SerialPort serial = null;
private DispatcherTimer testTimer;
private string[] testData = new string[] { ": 3.00 20.45 2355 1000 554\r\n", ": 5.00 78.09 1725 3200 121\r\n", ": 9.20 10.12 1492 8820 197\r\n" }; //test data to be sent when liveData is set to false.
private int testDataIndex = -1;
private DateTime dateOflastMessageHandled;
public enum PortStatus
{
Connected,
Disconnected
}
public PortStatus Status { get; private set; }
public bool LiveData { get; private set; }
public int MillisecondsDelayBetweenMessages { get; private set; }
public class MessageEventArgs : EventArgs
{
public string Message { get; private set; }
public MessageEventArgs(string message)
{
Message = message;
}
}
public delegate void MessageReceivedHandler(object sender, MessageEventArgs e);
public event MessageReceivedHandler OnMessageReceived;
private void MessageReceived(string message)
{
if (OnMessageReceived == null)
{
return;
}
OnMessageReceived(this, new MessageEventArgs(message));
}
public Port()
{
Status = PortStatus.Disconnected;
}
public void Connect(string portName, int baudRate, bool liveData, int millisecondsDelayBetweenMessages)
{
LiveData = liveData;
MillisecondsDelayBetweenMessages = millisecondsDelayBetweenMessages;
Disconnect();
if (liveData)
{
serial = new SerialPort();
serial.PortName = portName;
serial.BaudRate = baudRate;
serial.Handshake = Handshake.None;
serial.Parity = Parity.None;
serial.DataBits = 8;
serial.StopBits = StopBits.One;
serial.ReadTimeout = 200;
serial.WriteTimeout = 50;
serial.Open();
serial.DataReceived += new SerialDataReceivedEventHandler(Receive);
}
else
{
testTimer = new DispatcherTimer();
testTimer.Interval = new TimeSpan(0, 0, 0, 0, 3);
testTimer.Tick += new EventHandler(testTimer_Tick);
testTimer.Start();
}
Status = PortStatus.Connected;
}
private void testTimer_Tick(object sender, EventArgs e)
{
if (dateOflastMessageHandled == null || DateTime.Now.Subtract(dateOflastMessageHandled).TotalMilliseconds >= MillisecondsDelayBetweenMessages)
{
dateOflastMessageHandled = DateTime.Now;
MessageReceived(testData[testDataIndex]);
testDataIndex++;
if (testDataIndex >= testData.Length)
{
testDataIndex = 0;
}
}
}
private void Receive(object sender, SerialDataReceivedEventArgs e)
{
if (dateOflastMessageHandled == null || DateTime.Now.Subtract(dateOflastMessageHandled).TotalMilliseconds >= MillisecondsDelayBetweenMessages)
{
dateOflastMessageHandled = DateTime.Now;
Application.Current.Dispatcher.BeginInvoke(new Action(
delegate()
{
//MessageReceived(serial.ReadLine());
MessageReceived(serial.ReadExisting());
}));
}
}
public void Disconnect()
{
if (testTimer != null)
{
testTimer.Stop();
}
testDataIndex = 0;
Status = PortStatus.Disconnected;
if (serial != null)
{
serial.Close();
}
}
}
And finally in my MainWindow.xaml, this just shows the last message received:
<Button Content="Connect" Click="Connect_Port" Name="Connect_btn" />
<TextBlock Text="{Binding LastCOMMessage, ElementName=this}" />
Any hints or help with this would be much appreciated, as this is the first time I've worked w/ ports. Thanks!

video streaming from android to media player in C#

i want to make a simple video streaming. the application i used is android and simple media player using c#. most of the code i review will have POST method to the ip server. meanwhile my application is using gsm network which it will require to use data packet in transferring data media.
my first step is having an android application which can be record. this step is done. this is my code.
public class Videotest1Activity extends Activity implements
SurfaceHolder.Callback, OnInfoListener, OnErrorListener{
Camera camera;
VideoView videoView;
SurfaceHolder holder;
TextView msg;
Button initBtn, startBtn, stopBtn, playBtn, stprevBtn;
MediaRecorder recorder;
String outputFileName;
static final String TAG = "RecordVideo";
int maxDuration = 7000;//7sec
int frameRate = 1;//15
String serverIP = "172.19.117.12";
int serverPort = 2000;
Socket socket;
int mCount;
//TimerThread mTimer;
Chronometer chronometer;
LocalSocket receiver,sender;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_videotest1);
videoView = (VideoView) findViewById(R.id.videoView1);
initBtn = (Button) findViewById(R.id.initialize);
startBtn = (Button) findViewById(R.id.button1);
stopBtn = (Button) findViewById(R.id.button3);
msg = (TextView) findViewById(R.id.textView1);
playBtn = (Button) findViewById(R.id.reviewBtn);
stprevBtn = (Button) findViewById(R.id.stprevBtn);
chronometer = (Chronometer) findViewById(R.id.chronometer1);
/*
mTimer= new TimerThread();
mTimer.setOnAlarmListener(mSTimer_OnAlarm);
mTimer.setPeriod(100);
*/
}
public void buttonTapped(View view){
switch(view.getId()){
case R.id.initialize:
initRecorder();
break;
case R.id.button1:
beginRecording();
break;
case R.id.button3:
stopRecording();
break;
case R.id.reviewBtn:
playRecording();
break;
case R.id.stprevBtn:
stopPlayback();
break;
}
}
#Override
public void onError(MediaRecorder mr, int what, int extra) {
Log.e(TAG, "Record error");
stopRecording();
Toast.makeText(this, "Recording limit reached", 2500).show();
}
#Override
public void onInfo(MediaRecorder mr, int what, int extra) {
Log.i(TAG, "recording event");
if(what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED){
Log.i(TAG, "...max duration reached");
stopRecording();
Toast.makeText(this, "Recording limit info", 2500).show();
}
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
Log.v(TAG, "in surfaceCreated");
try{
camera.setPreviewDisplay(holder);
camera.startPreview();
}catch(IOException e){
Log.v(TAG, "Could not start the preview");
e.printStackTrace();
}
initBtn.setEnabled(true);
startBtn.setEnabled(true);
stopBtn.setEnabled(true);
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
}
protected void onResume(){
Log.v(TAG, "in onResume");
super.onResume();
initBtn.setEnabled(false);
startBtn.setEnabled(false);
stopBtn.setEnabled(false);
playBtn.setEnabled(false);
stprevBtn.setEnabled(false);
if(!initCamera())
finish();
}
public boolean initCamera(){
try{
camera = Camera.open();
Camera.Parameters camParam = camera.getParameters();
camera.lock();
holder = videoView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
//Thread thread = new Thread(new hantarThread());
//thread.start();
}catch(RuntimeException re){
Log.v(TAG, "Could not initialize the camera");
re.printStackTrace();
return false;
}
return true;
}
public void initRecorder(){
if(recorder != null)return;
outputFileName = Environment.getExternalStorageDirectory() + "/videooutput.mp4";
File outputFile = new File(outputFileName);
if(outputFile.exists())
outputFile.delete();//knp nk dlt?
try{
Toast.makeText(this, "InitRecord", 2500).show();
camera.stopPreview();
camera.unlock();
recorder = new MediaRecorder();
recorder.setCamera(camera);
recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
recorder.setVideoSize(176, 144);
recorder.setVideoFrameRate(15);//15
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);//mpeg_4
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setMaxDuration(60000);
recorder.setPreviewDisplay(holder.getSurface());
recorder.setOutputFile(outputFileName);
recorder.prepare();
Log.v(TAG, "MediaRecorder initialized");
initBtn.setEnabled(false);
startBtn.setEnabled(true);
}catch(Exception e){
Log.v(TAG, "MediaRecorder failed");
e.printStackTrace();
}
}
public void beginRecording(){
//mCount = 0;
//mTimer.start();
try{
Log.v(TAG, "start Recording begin");
int stoppedMilliseconds = 0;
String chronoText = chronometer.getText().toString();
String array[] = chronoText.split(":");
if (array.length == 2) {
stoppedMilliseconds = Integer.parseInt(array[0]) * 60 * 1000
+ Integer.parseInt(array[1]) * 1000;
} else if (array.length == 3) {
stoppedMilliseconds = Integer.parseInt(array[0]) * 60 * 60 * 1000
+ Integer.parseInt(array[1]) * 60 * 1000
+ Integer.parseInt(array[2]) * 1000;
}
chronometer.setBase(SystemClock.elapsedRealtime() - stoppedMilliseconds);
//chronometer.setBase(SystemClock.elapsedRealtime());
chronometer.start();
Log.v(TAG, "timer start");
long dTime = chronometer.getDrawingTime();
long autoLink = chronometer.getAutoLinkMask();
Log.v(TAG, "getDrawingTime: " + dTime);
Log.v(TAG, "AutoLink: " + autoLink);
recorder.setOnInfoListener(this);
recorder.setOnErrorListener(this);
recorder.start();
msg.setText("Recording");
startBtn.setEnabled(false);
stopBtn.setEnabled(true);
}catch(Exception e){
Log.v(TAG, "start Recording failed");
e.printStackTrace();
}
}
public void stopRecording(){
if(recorder != null){
recorder.setOnErrorListener(null);
recorder.setOnInfoListener(null);
try{
recorder.stop();
Log.v(TAG, "stop Record Begin");
chronometer.stop();
Log.v(TAG, "Timer stop");
//mTimer.stop();
}catch(IllegalStateException e){
Log.e(TAG, "stop is ILLEGAL");
}
releaseRecorder();
msg.setText("");
releaseCamera();
startBtn.setEnabled(false);
stopBtn.setEnabled(false);
playBtn.setEnabled(true);
}
else{
Log.v(TAG, "video cannot stop. Video null");
long autoLink = chronometer.getAutoLinkMask();
Log.v(TAG, "stop aLink: " + autoLink);
long elapsedMillis = SystemClock.elapsedRealtime() - chronometer.getBase();
Log.v(TAG, "elapsedMillis: " + elapsedMillis);
}
}
private void releaseCamera(){
if(camera != null){
try{
camera.reconnect();
}catch(IOException e){
e.printStackTrace();
}
camera.release();
camera = null;
}
}
private void releaseRecorder(){
if(recorder != null){
recorder.release();
recorder = null;
}
}
private void playRecording(){
MediaController mc = new MediaController(this);
videoView.setMediaController(mc);
videoView.setVideoPath(outputFileName);
videoView.start();
stprevBtn.setEnabled(true);
}
private void stopPlayback(){
videoView.stopPlayback();
}
}
}
next step i make is makes the media player can be play videooutput.mp4. in here, to make it play, it first must load the video then played. well, this is for the second step. it works well too. here's my code.
private void button6_Click_1(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
// create video source
FileVideoSource fileSource = new FileVideoSource(openFileDialog1.FileName);
// open it
OpenVideoSource(fileSource);
}
}
// Open video source
private void OpenVideoSource(IVideoSource source)
{
// set busy cursor
this.Cursor = Cursors.WaitCursor;
// stop current video source
CloseCurrentVideoSource();
// start new video source
videoSourcePlayer.VideoSource = source;
videoSourcePlayer.Start();
// reset stop watch
stopWatch = null;
// start timer
videoTimer.Start();
this.Cursor = Cursors.Default;
}
// New frame received by the player
private void videoSourcePlayer_NewFrame(object sender, ref Bitmap image)
{
DateTime now = DateTime.Now;
Graphics g = Graphics.FromImage(image);
// paint current time
SolidBrush brush = new SolidBrush(Color.Red);
g.DrawString(now.ToString(), this.Font, brush, new PointF(5, 5));
brush.Dispose();
g.Dispose();
}
// Close video source if it is running
private void CloseCurrentVideoSource()
{
if (videoSourcePlayer.VideoSource != null)
{
videoSourcePlayer.SignalToStop();
// wait ~ 3 seconds
for (int i = 0; i < 30; i++)
{
if (!videoSourcePlayer.IsRunning)
break;
System.Threading.Thread.Sleep(100);
}
if (videoSourcePlayer.IsRunning)
{
videoSourcePlayer.Stop();
}
videoSourcePlayer.VideoSource = null;
}
}
im using AForge for the media player in c#. All i did is adding the reference of AForge.Controls, AForge.Video and AForge.Video.DirectShow.
now, what i need to do is sending the media data to the media player(c#) byte by byte. i dont have a clue how to make this happen. i also found sample coding IP camera android which it bring the video to the server. however, i still dont have a clue to do it in my apps.
note that the gsm will require number phone of the simcard used and also port number of the modem gsm.
can anybody help me with this. or perhaps giving me some idea on modifying the code. any helps is appreciated. thanks for advance.

Categories