NAudio: Should I dispose a WaveOut object before each call to the Init method - naudio

I once read in a tutorial (unfortunately, I can't find where), that if I want to play several audio files, and use WaveOut, I should dispose the last WaveOut object before calling the Init method again. If not, I will get an error. However, I didn't dispose the objects, and everything works. I did this:
Mp3FileReader reader_1 = new Mp3FileReader("1.mp3");
Mp3FileReader reader_2 = new Mp3FileReader("2.mp3");
WaveOut WaveOutDevice = new WaveOut();
WaveOutDevice.Init(reader_1);
WaveOutDevice.Play();
and after a while, playing a second file:
WaveOutDevice.Init(reader_2);
WaveOutDevice.Play();
So I just want to be sure that I'm doing the right thing.

WaveOut was initially designed for Init to only be called a single time. In some circumstances it may work, but I'd recommend creating a new instance of WaveOut to play your next sound.

Related

How to read an arbitrary folder in a Universal app?

I'm trying to learn to write Universal apps, and I'm starting out by trying to recreate another project I wrote in WinForms. I need to be able to read from log files in an arbitrary folder, and as I understand it I need to get the users permissions to access the folder. I should then store an access token so I can re-read that folder in future. By reading around I've managed to cobble together the following code:
Friend Async Function GetLogFolder() As Task(Of StorageFolder)
Dim myLogFolder As StorageFolder
If ApplicationData.Current.LocalSettings.Values.ContainsKey("LogFolder") Then
Dim sToken As String = ApplicationData.Current.LocalSettings.Values("LogFolder")
myLogFolder = StorageApplicationPermissions.FutureAccessList.GetFileAsync(sToken)
Else
Dim myFolderPicker As FolderPicker = New FolderPicker
myFolderPicker.FileTypeFilter.Add("*")
myLogFolder = Await myFolderPicker.PickSingleFolderAsync
Dim sToken As String = StorageApplicationPermissions.FutureAccessList.Add(myLogFolder)
ApplicationData.Current.LocalSettings.Values.Add("LogFolder", sToken)
End If
Return myLogFolder
End Function
But it doesn't seem to work. At this stage I have a form containing just a TextBlock and Button. Clicking the Button calls a method that will parse all the *.log files in a given folder. The first thing it does is:
Dim myFolder As StorageFolder = GetLogFolder.Result
When the code runs, and I click the button, I get a folder browser dialog shown, but then everything freezes and I have to switch to Visual Studio and hit stop. I've probably made some silly error, but I can't figure out what it is.
Any help would be much appreciated.
The problem is very likely not caused by the file access code itself, but by the way you use the asynchronous API.
Because the GetLogFolder method returns a Task of StorageFolder, you will need to await the result instead of getting it using the Result property. The reason is that the async/await pattern allows you to do I/O work on a separate thread but return control back to the UI thread when finished. What you are doing here is to call the GetLogFolder method, in which you let the user choose a folder using FolderPicker. Here is the problem - the user is presented with a folder picker while the control returns to your code and you query the Result property of the Task returned by the GetLogFolder method. Querying the Result property causes the UI thread to stop and wait until the Task is finished to get the result. Unfortunately, when the user picks the folder, the control wants to return to the UI thread to continue executing the rest of the GetLogFolder method and we have a deadlock. Result property stopped the UI thread to wait for the Task result and the Task waits for the UI thread to become available. Neither can continue so the app completely freezes.
The solution is quite simple - using the async / await keywords. You can read up more about them in VB.NET here with a clear example.
In your case the first step would be to make the button's Click handler method async and then replace the code inside by the following:
Dim myFolder As StorageFolder = Await GetLogFolder

VB.NET Background Worker check propriety of the form TargetInvocationException

I'm working on a program that should find some image's urls from a website and should download them, i already wrote the parsing code and the downloading code, and it work, but since i noticed it's really slow i thought that it would be better if i make it work async from the form, so i created 2 background worker:
1) The parser
2) The downloader
When the parser starts the downloader starts too, the parser should add urls to a listbox, and the downloader should download them and delete from the list, i don't think it will be a problem to manage that, my real problem is... that i never used background worker...
The parser should load the page in a Webbrowser, than parse the images, but when i call the function navigate on the webbrowser... it stop giving me a TargetInvocationException.
I searched online, and from what i have seen it seems that backgrond workers cannot directly access to proprieties and methods of the GUI controls, from what i've understand it shold use Invoke, so i created a function that do all the work, and it check if the browser is in another thread or is in this thread by doing this:
Sub parse(ByVal url As String)
If wb.InvokeRequired Then 'wb is the Webbrowser
wb.Invoke(New Action(AddressOf prova))
Return
End If
'Navigate to the url, wait for browser to complete loading then do the parsing
End Sub
Now my problems are two:
1)The invokerequired propriety value is false even if i call the method from the worker, so the invoke is not called and it still give me the same exception
2)If i call invoke i should force the method to run in the GUI thread, right?
If so... shouldn't it slow my program as before?
I did it alone, the problem was that i created the components in runtime, so I should have created the handles for the components, it was enough to do something like this after creating the components:
If Not wb.IsHandleCreated Then
Dim handle As IntPtr = wb.Handle
End If
The variable handle is useless, but calling the handle propriety of the component it force the component to create the handle, that's why I made that assignment.

Cannot set URL after the fact on Ti.Media.createSound()

I can successfully play a remote mp3 via the Titanium.Media.Sound object, but there is a problem. The 1st clip always plays fine. But each time I try to play a different clip, the first clip plays again. This is 100% repeatable.
So at the top of my js file I'm doing this:
var soundPlayer = Ti.Media.createSound({allowBackground: false});
Then inside the event listener for a button click, I'm setting the URL thusly:
soundPlayer.setUrl(mp3URL);
And I have even tried this approach:
soundPlayer.url = mp3URL;
But they both have the same flaw: the audio is always still the first clip, never any clip I set afterward. I have verified via console logging that in fact a new url was handed to the sound player, and in fact the new url points at a valid mp3. It seems that once I set a url for the sound player, it is set in stone and cannot be changed--just replayed.
So then I tried a completely different approach. Inside my button click listener, I re-create the Sound object each time and hand in the new URL:
soundPlayer = Ti.Media.createSound({allowBackground: false, url: mp3URL});
This actually DOES work and plays the new url each time, BUT it has a terrible side effect: any attached event listeners no longer fire. I need to track state changes in the player, for example when it completes, etc. But these event listeners no longer fire when I take this approach.
Strangely, the AudioPlayer object behaves correctly in all respects, allows me to set new URLs, etc. BUT the problem with that is that AudioPlayer absolutely refuses to play any mp3 file smaller than 40Kb. I have posted questions around that issue on this and other forums, and based on responses and experimentation, I have lots of evidence for the 40Kb limitation, and no evidence to the contrary.
So why can't I change the url after object creation on the Sound object? Thanks in advance for any ideas.
I'd put this in the "Known bug" category, see here: https://jira.appcelerator.org/browse/TIMOB-3348 marked as "won't fix".
Bug report:
var sound = Titanium.Media.createSound();
sound.url='../cricket.wav'; sound.play();
But if I try to change the url after that, sound plays still the cricket.wav
sound.
Response from Appcelerator(?):
"Duplicate of customer issue TIMOB-1488. This can be easily achieved
by creating a new sound object. Furthermore, this would create a
platform parity issue and would complicate any future API that, for
example, would support sound channels, etc. A sound object should be
considered an immutable object once it's constructed."
So create a new sound object and re-add the event listeners is the solution I think:
var sampleListener = function(){
alert('something happened');
}
var sound = Ti.Media.createSound({url:myURL});
sound.addEventListener('complete', sampleListener);
sound.play();
//later on, make a new sound object:
sound = Ti.Media.createSound({url:anotherURL});
sound.addEventListener('complete', sampleListener);
sound.addEventListener('someevent', anotherSampleListener);
sound.play();
Just so know, this is happening to the Ti.Media.AudioPlayer also. The proposed solution will work just fine in that case as well.

Objective-c, passing NSURLConnection result to a View Controller

Long time reader, first time poster here.
I'm creating a test app that creates a NSURLConnection and then displays the result on an UILabel.
I am presently using a Notification Center observer, which fires a notification from within connectionDidFinishLoading to wait for the connection to complete successfully, before I look for the result.
However, what I am struggling to conceptualize is where to store the response data so that I can access it from my View Controller and post the result to the UILabel. (Or from anywhere other than an instance of my Connection Class, for that matter.)
I don't want to post directly to the UILabel from connectionDidFinishLoading. I need a way to decide what I will do with the response later - so my Connection Class stays generalized.
I need a better way to save the response data somewhere, where I can reference it after the instance of the Connection Class has terminated.
Ideally, it should be somewhere that I can have multiple instances of the Connection Class open, and access each response in turn as I need them. This eliminates the potential to just create a variable in my View Controller or somewhere else more global and dump the response to it.
Any ideas on what design patterns could/should be used here would be greatly appreciated!
My suggestions for you to start with are :
Make a singleton class. I will have a property NSDictionary * info or NSArray *infoList; You will have acces to the same data from wherever the app. Update the property, post the notification, access the property from the viewController.
Store the info into a plist/file. Serialize the information, or save plain stream. Whatever you like.Thus after you finish writing to the file, post the notification, read from the file from anyplace within the app.
In both cases if you want multiple connections i suggest going for the factory design Pattern.

EXC BAD ACCESS from CoreGraphics API in NSOperation

I'm trying to do some CoreGraphics/CoreImage manipulation inside an NSOperation, using MacRuby. I have a few API calls that read a source file into CG and set up a CGImageDestination.
If I put the following code into an NSOperation.init, everything works great:
#dest = CGImageDestinationCreateWithURL(#photo.output_url, "public.jpeg" , 1, nil);
#context = CIContext.alloc.init
#cgOriginalImgSrc = CGImageSourceCreateWithURL(#photo.url, nil)
#cgOriginal = CGImageSourceCreateImageAtIndex(#cgOriginalImgSrc, 0, nil)
But if I put the same code into the main function for the NSOperation, I get sporadic EXC_BAD_ACCESS errors. And only when passing the NSOperation to an NSOperationQueue; if I invoke main myself, it works just fine.
At the end of the main I am running:
CFRelease(#dest)
CFRelease(#cgOriginalImgSrc)
CGImageRelease(#cgOriginal)
Even stranger is that it works in init, even if init isn't invoked from the main thread (so not a main thread/background thread issue, I'm guessing)
Any thoughts?
Looks like one of your threads is referring to an object that doesn't exist in memory anymore. Try removing
CFRelease(#dest)
CFRelease(#cgOriginalImgSrc)
CGImageRelease(#cgOriginal)
And see how it goes. Also you can try verifying your objects in each queue to see if they are still available. Finally, you could use macrubyd, the debugger for MacRuby to see what's going on, or even use GDB and paste the backtrace so we can see what the problem is.
Thanks,
Matt