I have set play/pause button enabled and also added target event to each but when ever I click button in simulator it always calls play button's target event and button's image not properly updating from play to pause and vice versa. Any one have idea regards this?
Note: To play/pause audio I have used Plugin.MediaManager.Forms nuget (version 0.9.7)
[Export("playableContentManager:initiatePlaybackOfContentItemAtIndexPath:completionHandler:")]
public override void InitiatePlaybackOfContentItem(MPPlayableContentManager contentManager, NSIndexPath indexPath, Action<NSError> completionHandler)
{
DispatchQueue.MainQueue.DispatchAsync(() =>
{
UIApplication.SharedApplication.EndReceivingRemoteControlEvents();
UIApplication.SharedApplication.BeginReceivingRemoteControlEvents();
var song = CarPlaylist[indexPath.Section].episodes[indexPath.Row];
var NowPlayingInfoCenter = MPNowPlayingInfoCenter.DefaultCenter;
MPNowPlayingInfo playingInfo = new MPNowPlayingInfo();
playingInfo.Title = song.Title;
playingInfo.Artist = song.Editor;
playingInfo.PlaybackDuration = song.Duration.TotalSeconds; //provide time in seconds
playingInfo.MediaType = MPNowPlayingInfoMediaType.Audio;
playingInfo.Artwork = new MPMediaItemArtwork(image: ExtractArtWork.UIImageFromUrl(song.ArtWork));
playingInfo.AssetUrl = new NSUrl(song.FileUrl.AbsolutePath);
playingInfo.PlaybackRate = song.IsPlaying ? 1.0 : 0.0;
NowPlayingInfoCenter.NowPlaying = playingInfo;
var currentPlayItemId = episode.PodcastId.ToString();
string[] identifier = new string[1];
identifier[0] = currentPlayItemId;
contentManager = MPPlayableContentManager.Shared;
contentManager.NowPlayingIdentifiers = identifier;
contentManager.DataSource = new AppDelegateDataSource(CarPlaylist);
var commandCenter = MPRemoteCommandCenter.Shared;
commandCenter.PlayCommand.Enabled = true;
commandCenter.PauseCommand.Enabled = true;
commandCenter.PlayCommand.AddTarget(PlayButton);
commandCenter.PauseCommand.AddTarget(PauseButton);
completionHandler(null);
UIApplication.SharedApplication.EndReceivingRemoteControlEvents();
UIApplication.SharedApplication.BeginReceivingRemoteControlEvents();
});
}
public MPRemoteCommandHandlerStatus PlayButton(MPRemoteCommandEvent commandEvent)
{
//Logic to update app UI to play mode and play audio
return MPRemoteCommandHandlerStatus.Success;
}
public MPRemoteCommandHandlerStatus PauseButton(MPRemoteCommandEvent commandEvent)
{
//Logic to update app UI to pause mode and pause audio
return MPRemoteCommandHandlerStatus.Success;
}
Related
I've been wracking my brain at this for awhile now. I've looked all over on SO already and I'm not finding any answers to my problem here. What I'm attempting to accomplish is a function that will allow my to select an input card for a microphone and output card to go to a radio. This code works on the initial try, but once i stop "Transmitting" you can hear what sounds like a doubled up audio stream and it becomes laggy and eventually crashes with a buffer full exception. I'm not sure what i'm doing wrong here.
public WaveOutEvent outputDevice = new WaveOutEvent() { DeviceNumber = -1 };
public WaveInEvent inputDevice = new WaveInEvent() { DeviceNumber = -1 };
public bool transmit = false;
public bool markerActive = false;
public bool alert1Active = false;
public SerialPort port = new SerialPort();
public string[] ports = SerialPort.GetPortNames();
private BufferedWaveProvider bufferedWaveProvider;
public string keyTransmitter()
{
string label;
if (transmit)
{
transmit = false;
port.DtrEnable = false;
port.RtsEnable = false;
label = "Transmit";
bufferedWaveProvider.ClearBuffer();
inputDevice.StopRecording();
inputDevice.Dispose();
outputDevice.Dispose();
outputDevice.Stop();
}
else
{
transmit = true;
port.DtrEnable = true;
port.RtsEnable = true;
label = "Transmitting";
bufferedWaveProvider = new BufferedWaveProvider(inputDevice.WaveFormat);
inputDevice.DataAvailable += OnDataAvailable;
inputDevice.StartRecording();
outputDevice.Init(bufferedWaveProvider);
outputDevice.Play();
}
return label;
}
public void OnDataAvailable(object sender, WaveInEventArgs args)
{
bufferedWaveProvider.AddSamples(args.Buffer, 0, args.BytesRecorded);
//bufferedWaveProvider.DiscardOnBufferOverflow = true;
}
A BufferedWaveProvider has a size limit, so it must be changed if it wants more audio, but it will eventually overload, so we'll use "DiscardOnBufferOverflow", so here's the code example:
NOTE: if you are using a single reproduction, it is not necessary to change BufferedWaveProvider to a new one.
BufferedWaveProvider waveChannel = new BufferedWaveProvider(INFO HERE);
waveChannel.BufferDuration = new TimeSpan(0, 1, 0); //BufferDuration, 1 minute
waveChannel.DiscardOnBufferOverflow = true; //The name says
It will not be necessary to use "init" or "play" again, because BufferedWaveProvider, when not buffered, it generates silence for WaveOut
English from google translator
I'm building a MMVMLight application which at some point have to upload files to an azure storage account and then in case of success will update some data in a SQL server.
My method works this way :
public ICommand UploadCICommand
{
get
{
if (_UploadCICommand == null)
{
_UploadCICommand = new RelayCommand(async () =>
{
try
{
ProgressDialogController controller;
// next upload CI
MetroDialogSettings dialogSettings = new MetroDialogSettings { AnimateHide = false, AnimateShow = true };
if ((await dialogCoordinator.ShowMessageAsync(this, "Confirm", $"Are you sure want to upload {appName} ?", MessageDialogStyle.AffirmativeAndNegative, (new MetroDialogSettings { AnimateHide = false, AnimateShow = true })) == MessageDialogResult.Affirmative))
{
controller = await dialogCoordinator.ShowProgressAsync(this, "Please Wait...", string.Empty, false, (new MetroDialogSettings { AnimateHide = false, AnimateShow = false }));
controller.SetMessage($"Uploading content");
CloudBlobContainer container = new CloudBlobContainer(new Uri(sasUri));
ICloudBlob blob = container.GetBlockBlobReference(zipFile);
BlobTransfer blobTransfer = new BlobTransfer();
blobTransfer.TransferCompleted += new AsyncCompletedEventHandler(blobTransfer_TransferCompleted);
blobTransfer.TransferProgressChanged += new EventHandler<BlobTransfer.BlobTransferProgressChangedEventArgs>(blobTransfer_TransferProgressChanged);
blobTransfer.UploadBlobAsync(blob, zipFile);
//And then, the code to update database....
}
}
}
}
}
}
void blobTransfer_TransferProgressChanged(object sender, BlobTransfer.BlobTransferProgressChangedEventArgs e)
{
var SetDebugBreakPointIfNeededHere = 1;
//Main stuff to do
// Parent object of sender -> controller.SetProgress(e.ProgressPercentage);
// Other information that would be cool to show
//Speed = (e.Speed / 1024 / 1024).ToString("N0");
//TimeRemaining = e.TimeRemaining.ToString();
//Progress = e.ProgressPercentage;
//SizeDowloaded = (e.BytesSent / 1024 / 1024).ToString("N0");
}
void blobTransfer_TransferCompleted(object sender, AsyncCompletedEventArgs e)
{
var SetDebugBreakPointIfNeededHere = 1;
//EndTime = System.DateTime.Now;
//if (e.Cancelled)
//{
// Log cancel and try preventing main function to continue
//}
//else if (e.Error != null)
//{
// Log failure and try preventing main function to continue
//}
//else
//{
// Speed = ((((BlobSize) / 1024 / 1024) / (EndTime - StartTime).TotalSeconds)).ToString("N0");
// Let the caller method continue
//}
}
What I would like to achieve is :
Wait TransferCompleted event to be triggered before if go to the update DB part
And while I'm waiting the end of the upload to update the progressbar by calling "controller.SetProgress();" in my TransferProgressChanged but in this method I don't have access to the controller object.
So far what I have thought about is
For point 1 : Set my "DB update code" in the blobTransfer_TransferCompleted method to be sure it's not get called until the event is triggered
For point two : As the sender of the progress changed event is my BlobTransfer object I still don't know how to call the set progress method of my dialog. I was maybe thinking about using reflexion to get the parent object of my sender and try to update the value here.
What I'm quite sure of is that both of my ideas are not smart but right now I cannot figure out a clever way to do this.
I finally found the Microsoft Azure Storage Data Movement Library which works in a more modern way :
CloudBlobContainer container = new CloudBlobContainer(new Uri(sasUri));
CloudBlockBlob blob = container.GetBlockBlobReference(Path.GetFileName(zipFile));
// Setup the number of the concurrent operations
TransferManager.Configurations.ParallelOperations = 64;
// Setup the transfer context and track the upoload progress
SingleTransferContext context = new SingleTransferContext();
context.ProgressHandler = new Progress<TransferStatus>((progress) =>
{
int percentage = (int)Math.Round((double)((double)progress.BytesTransferred / (double)zipFileInfo.Length * 100));
//controller.SetProgress(percentage);
controller.SetMessage($"Uploading content {percentage}%");
});
context.ShouldOverwriteCallbackAsync = new ShouldOverwriteCallbackAsync(ShouldTransferCallback);
// Upload a local blob
await TransferManager.UploadAsync(
zipFile, blob, null, context, CancellationToken.None);
with ShouldTransferCallback always returning true as I want to overwrite blobs each time.
private async Task<bool> ShouldTransferCallback(object source, object dest)
{
return true;
}
Just noticed the title gets shown top and bottom of the toast now in a C# application I'm building. Anyone else see the same thing? In pre-anniversary Windows 10, the BalloonTipTitle only appeared in the top portion of the toast.
Not a big deal, but it looks silly.
I can't post pictures yet, but if I get any responses I'll upload pre and post-anniversary pictures of the toast behavior.
I think I'm getting downvoted because it wasn't really a question. So I'll rephrase:
Windows 10 Anniversary is putting the BalloonTipTitle at the top, and assembly: AssemblyTitle from AssemblyInfo.cs at the bottom of the toast.
What's the best way to manage this across different versions of Windows 10 and 7? I want my user to know my app caused the toast, but I don't want to duplicate information.
Here's some quick code in a Windows Forms Application that shows what I mean. If you change the BalloonTipTitle to match your solution name, you'll see the redundant title:
static void Main()
{
NotifyIcon myNotifyIcon = new NotifyIcon();
myNotifyIcon.BalloonTipIcon = ToolTipIcon.Warning;
myNotifyIcon.BalloonTipText = "This is a test toast";
myNotifyIcon.BalloonTipTitle = "Toast Title";
myNotifyIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
myNotifyIcon.Visible = true;
myNotifyIcon.ShowBalloonTip(10000);
ContextMenuStrip contextMenu = new ContextMenuStrip();
ToolStripMenuItem menuItemExit = new ToolStripMenuItem();
menuItemExit.Text = "Exit";
contextMenu.Items.Add(menuItemExit);
menuItemExit.Click += delegate { myNotifyIcon.Visible = false; Application.Exit(); };
myNotifyIcon.ContextMenuStrip = contextMenu;
System.Timers.Timer myTimer = new System.Timers.Timer();
myTimer.Interval = 20000;
myTimer.Enabled = true;
myTimer.Elapsed += delegate { myNotifyIcon.ShowBalloonTip(10000); };
Application.Run();
}
Decided to check the CurrentBuild registry key after checking for Windows 10. Anything greater than or equal to build 14393 (Anniversary), and I'll leave out the BalloonTipTitle
bool AppNameInBaloon = false;
string BuildString = ReadHKLMValue(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentBuild");
int CurrentBuild;
bool WasParsed = Int32.TryParse(BuildString, out CurrentBuild);
if (WasParsed)
{
if (CurrentBuild >= 14393)
{
AppNameInBaloon = true;
}
}
private static string ReadHKLMValue(string regPath, string value)
{
RegistryKey localKey;
if (Environment.Is64BitOperatingSystem)
{
localKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
}
else
{
localKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
}
string keyValue;
try
{
keyValue = localKey.OpenSubKey(regPath).GetValue(value).ToString();
return keyValue;
}
catch
{
keyValue = "";
}
return keyValue;
}
I can't seem to record the audio from default audio device, and play it on another audio device..
I don't want to record the microphone, but the audio device..
When I play a movie, I can hear sound, through my headphones, I want to copy that sound to any audio device I choose..
If you have any suggestions, it doesn't have to be with NAudio..
As far as I can tell, NAudio can't do this..
This is the code I use for the task at this time, but it only takes input from my Microphone: Code snippet with NAudio..
void playSoundCopy(int dv0)
{
disposeWave0();// stop previous sounds before starting
var waveOut0 = new WaveOut();
waveOut0.DeviceNumber = dv0;
wave0 = waveOut0;
Defaultwave0 = new WaveIn();
Defaultwave0.DeviceNumber = (int)GetDefaultDevice(Defaultdevice.FriendlyName);
var waveinReader0 = new WaveInProvider(Defaultwave0);
wave0.Init(waveinReader0);
play0 = false;
Thread.Sleep(1000);
play0 = true;
t0 = new Thread(() => { timeline0(); });
t0.IsBackground = true;
t0.Start();
Defaultwave0.StartRecording();
wave0.Play();
}
The real problem is actually that I can't record from a WaveOut device, only WaveIn..
Working Result:
void playSoundCopy(int dv0)
{
disposeWave0();// stop previous sounds before starting
var waveOut0 = new WaveOut();
waveOut0.DeviceNumber = dv0;
wave0 = waveOut0;
var format0 = Defaultdevice.AudioClient.MixFormat;
buffer0 = new BufferedWaveProvider(format0);
wave0.Init(buffer0);
capture = new WasapiLoopbackCapture(Defaultdevice);
capture.ShareMode = AudioClientShareMode.Shared;
capture.DataAvailable += CaptureOnDataAvailable;
play0 = false;
Thread.Sleep(1000);
play0 = true;
t0 = new Thread(() => { timeline0(); });
t0.IsBackground = true;
t0.Start();
capture.StartRecording();
wave0.Play();
}
void CaptureOnDataAvailable(object sender, WaveInEventArgs waveInEventArgs)
{
try
{
var itm = new byte[waveInEventArgs.BytesRecorded];
Array.Copy(waveInEventArgs.Buffer, itm, waveInEventArgs.BytesRecorded);
buffer0.AddSamples(itm, 0, itm.Length);
}
catch { }
}
You can capture audio being sent to a device using WasapiLoopbackCapture. Then you could pipe that into a BufferedWaveProvider and use that to feed another output device. There would be some latency introduced though, so don't expect the two devices to be in sync.
I am trying to use async and await in my coding while I transfer big amounts of data from my WCF service to my WPF client application. Now it does take about 2-3 minutes to load the data, but now I struggle with my UI that's unresponsive for that total time. It's not very user-friendly. Is there a way to get my my UI responsive while the data loads with the coding that I currently have?
public pgSysproStock()
{
InitializeComponent();
SysproStock.WindowState = WindowState.Normal;
this.UpdateStockAsync();
}
private async void UpdateStockAsync()
{
dgSysproStock.IsEnabled = false;
using (TruckServiceClient TSC = new TruckServiceClient())
{
var allStock = await TSC.GetSysproStockAsync();
dgSysproStock.ItemsSource = allStock.Select(item =>
new AllStock
{
Id = item.Id,
StockCode = item.StockCode,
Description = item.Description,
ConvFactAltUom = item.ConvFactAltUom,
ConvMulDiv = item.ConvMulDiv,
ConvFactOthUom = item.ConvFactOthUom,
MulDiv = item.MulDiv,
Mass = item.Mass,
Updated_Supplier = item.Updated_Supplier,
CycleCount = item.CycleCount,
ProductClass = item.ProductClass.ToString(),
UnitCost = item.UnitCost,
Discount = item.Discount,
Warehouse = item.Warehouse,
MinimumStock = item.MinimumStock,
MaximumStock = item.MaximumStock,
StockForNow = item.StockForNow,
CoilWidth = item.CoilWidth,
SheetCoilLength = item.SheetCoilLength,
MaterialThickness = item.MaterialThickness
}).ToArray();
dgSysproStock.IsEnabled = true;
}
}
Thank you for any advice! :D
It seems that your operation is initiating operation incorrectly.
I suggest you create handler On Load or some other event for your window, mark it async and do the call from there. Should be simple as this:
private async void Form1_Load(object sender, EventArgs e)
{
dgSysproStock.IsEnabled = false;
using (TruckServiceClient TSC = new TruckServiceClient())
{
var allStock = await TSC.GetSysproStockAsync();
dgSysproStock.ItemsSource = allStock.Select(item =>
new AllStock
{
...
}).ToArray();
dgSysproStock.IsEnabled = true;
}
}
Note that I'm using Form.Load event but you may use different.