Search code examples
iospluginstouchmvvmcrossexporter

GetAudio Plugin for MvvmCross


I'm developing an plugin for MvvmCross to GetAudio from the device. But I'm getting an error in the Touch implementation. I've already took a look at here, here and here.

But nothing fixed my problem.

Well, so far I have:

        var audioDelegate = new AudioDelegate();
        audioDelegate.AudioAvailable = ProcessAudio;
        mediaPicker = new MPMediaPickerController(); 
        mediaPicker.Delegate = audioDelegate;
        mediaPicker.AllowsPickingMultipleItems = false;
        modalHost.PresentModalViewController (mediaPicker, true);

To start the picker from audio, where AudioDelegate is:

    private class AudioDelegate : MPMediaPickerControllerDelegate
    {
        public EventHandler<MvxAudioRecorderEventArgs> AudioAvailable;

        public override void MediaItemsPicked (MPMediaPickerController sender, MPMediaItemCollection mediaItemCollection)
        {
            if (mediaItemCollection.Count < 1) 
            {
                return;
            }
            MvxAudioRecorderEventArgs eventArg = new MvxAudioRecorderEventArgs (mediaItemCollection.Items [0].AssetURL);
            AudioAvailable (this, eventArg);
        }
    }

And then in ProcessAudio:

    private void ProcessMedia(object sender, UIImagePickerMediaPickedEventArgs e)
    {
        var assetURL = e.MediaUrl;
        NSDictionary dictionary = null;
        var assetExtension = e.MediaUrl.Path.Split ('.') [1];

        var songAsset = new AVUrlAsset (assetURL, dictionary);
        var exporter = new AVAssetExportSession (songAsset, AVAssetExportSession.PresetPassthrough.ToString ());
        exporter.OutputFileType = (assetExtension == "mp3") ? "com.apple.quicktime-movie" : AVFileType.AppleM4A;
        var manager = new NSFileManager ();

        var count = 0;
        string filePath = null;
        do 
        {
            var extension = "mov";//( NSString *)UTTypeCopyPreferredTagWithClass(( CFStringRef)AVFileTypeQuickTimeMovie, kUTTagClassFilenameExtension);
            var fileNameNoExtension = "AUD_" + Guid.NewGuid ().ToString ();
            var fileName = string.Format ("{0}({1})", fileNameNoExtension, count);
            filePath = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments) + "/";
            filePath = filePath + fileName + "." + extension;
            count++;

        } while (manager.FileExists (filePath));

        var outputURL = new NSUrl (filePath);//should be something in objective C... => [NSURL fileURLWithPath:filePath];

        exporter.OutputUrl = outputURL;


        exporter.ExportAsynchronously ( () =>
            {
                var exportStatus = exporter.Status;
                switch (exportStatus) 
                {
                    case AVAssetExportSessionStatus.Unknown:
                    case AVAssetExportSessionStatus.Completed: 
                    {
                        //remove the .mov from file and make it available for callback mediaAvailable()...
                        break;
                    }
                    case AVAssetExportSessionStatus.Waiting:
                    case AVAssetExportSessionStatus.Cancelled:
                    case AVAssetExportSessionStatus.Exporting:
                    case AVAssetExportSessionStatus.Failed: 
                    default:
                    {
                        var exportError = exporter.Error;
                        if(assumeCancelled != null)
                        {
                            assumeCancelled();
                        }
                        break;
                    }
                }
            });


        mediaPicker.DismissViewController(true, () => { });
        modalHost.NativeModalViewControllerDisappearedOnItsOwn();
    }

But it is always with Status.Failed with error:

        LocalizedDescription: The operation could not be completed

        Description: Error Domain=AVFoundationErrorDomain Code=-11800 
        "The operation could not be completed" UserInfo=0x1476cce0 
        {NSLocalizedDescription=The operation could not be completed, 
        NSUnderlyingError=0x1585da90 "The operation couldn’t be completed.
        (OSStatus error -12780.)", NSLocalizedFailureReason=An unknown error
        occurred (-12780)}

Can anyone help me? Thanks in regard,


Solution

  • Found the solution. As I thought the error was in the outputURL file.

    Changed it to:

            var count = 0;
            string filePath = null;
            do 
            {
                var extension = "mp3.mov";//( NSString *)UTTypeCopyPreferredTagWithClass(( CFStringRef)AVFileTypeQuickTimeMovie, kUTTagClassFilenameExtension);
                var fileNameNoExtension = "AUD_" + Guid.NewGuid ().ToString ();
                var fileName = (count == 0) ? fileNameNoExtension : string.Format ("{0}({1})", fileNameNoExtension, count);
                filePath = NSBundle.MainBundle.BundlePath + "/../tmp/" + fileName; /* HERE WAS THE FIRST PROBLEM, USE NSBUNDLE... */
                filePath = filePath + fileName + "." + extension;
                count++;
    
            } while (manager.FileExists (filePath));
            var outputURL = NSUrl.FromFilename(filePath); /* HERE WAAS THE SECOND PROBLEM, CREATE IT WITH FROMFILENAME INSTEAD OF NEW... */
    

    And then in the export, just remove the .mov extension...

            var withoutMOVPath = outputURL.Path.Remove(outputURL.Path.Length - 4);
            NSError error = null;
            manager.Move (outputURL.Path, withoutMOVPath, out error);
    
                if(error != null && assumeCancelled != null)
                {
                    assumeCancelled();
                    return;
                }
    
            var mediaStream = new FileStream (withoutMOVPath, FileMode.Open);
            mediaAvailable (mediaStream);
            break;