Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Opening a file from the iPod library makes EZAudioFile crash #12

Closed
jbouaziz opened this issue Jan 12, 2014 · 18 comments
Closed

Opening a file from the iPod library makes EZAudioFile crash #12

jbouaziz opened this issue Jan 12, 2014 · 18 comments

Comments

@jbouaziz
Copy link

Hey!

I tried to open an MPMediaItem file using this code:

// Get asset url
//
NSURL *assetURL = [item valueForProperty:MPMediaItemPropertyAssetURL];
self.asset = [AVAsset assetWithURL:assetURL];
self.audioFile = [EZAudioFile audioFileWithURL:assetURL];


// Set up waveform
//
[self.audioFile getWaveformDataWithCompletionBlock:^(float *waveformData, UInt32 length) {

    // Update the audio plot with the waveform data
    //
    self.audioPlot.plotType = EZPlotTypeBuffer;
    [self.audioPlot updateBuffer:waveformData withBufferSize:length];
}];

I also tried using to copy the song in a temporary folder using AVAssetExportSession but it didn't work.

file:///private/var/mobile/Applications/B0746B0F-46A6-4292-94D3-49F3A6E22DD8/tmp/tempBase.m4a
@syedhali
Copy link
Owner

Interesting, I think URLs referenced by the MPMediaItem can only be opened using the AVFoundation. I'll take a look and see if I can find a way around.

@jbouaziz
Copy link
Author

Are you planning on integrating it in EZAudio 1.0?

@raghunathkavuri
Copy link

Hi SyedhAli,
Great work on EZAudio and thanks.
I'm using EZAudio for applying custom audio equalization in our video player project.
I was able to open the MPMediaItem url and play it in the iOS 7.0+ version of iPad but not on the versions < iOS 7.0.

Also, frequent change to seek position (scrubbing the slider) crashes the application with EXC_BAD_ACCESS.

@rmutter
Copy link

rmutter commented Feb 10, 2015

@raghunathkavuri how did you get this working? Any advice would be appreciated!

@syedhali was a solution to this ever figured out? When creating a new EZAudioFile with the MPMediaItem's assetURL, I'm getting a crash here:

  [EZAudio checkResult:ExtAudioFileSetProperty(_audioFile,
                                               kExtAudioFileProperty_ClientDataFormat,
                                               sizeof (AudioStreamBasicDescription),
                                               &_clientFormat)
             operation:"Couldn't set client data format on input ext file"];

@nitingohel
Copy link

Having the same issue get EXC_BAD_ACCESS at

[EZAudio checkResult:ExtAudioFileSetProperty(_audioFile,
kExtAudioFileProperty_ClientDataFormat,
sizeof (AudioStreamBasicDescription),
&_clientFormat)
operation:"Couldn't set client data format on input ext file"];

With AssetURL

@tspent
Copy link

tspent commented Jun 13, 2015

Guys did you found any solution?

@syedhali
Copy link
Owner

So any file coming from the iPod library as an MPMediaItem will have a path prefix, ipod://, which doesn't agree with the EZAudioFile. Here's an approach to create an EZAudioFile using the AVAssetExportSession to export the audio data from the MPMediaItem to the app's bundle.

//
// Creates an EZAudioFile from an MPMediaItem representing a song coming from
// an iOS device's iPod library. Since an MPMediaItem's URL is always prefixed
// with an ipod:// path we must use the AVAssetExportSession to first export
// the song to a file path that the EZAudioFile can actually find in the app's bundle.
//
- (void)openMediaItem:(MPMediaItem *)item
           completion:(void(^)(EZAudioFile *audioFile, NSError *error))completion
{
    NSURL *url = [item valueForProperty:MPMediaItemPropertyAssetURL];
    NSString *title = [item valueForProperty:MPMediaItemPropertyTitle];
    if (url)
    {
        //
        // Create an AVAudioExportSession to export the MPMediaItem to a non-iPod
        // file path url we can actually use for an EZAudioFile
        //
        AVURLAsset *asset = [AVURLAsset assetWithURL:url];
        AVAssetExportSession *exporter = [AVAssetExportSession exportSessionWithAsset:asset
                                                                           presetName:AVAssetExportPresetAppleM4A];
        exporter.outputFileType = @"com.apple.m4a-audio";
        NSString *exportURLPath = [[self applicationDocumentsDirectory] stringByAppendingFormat:@"/%@.m4a", title];
        NSURL *exportURL = [NSURL fileURLWithPath:exportURLPath];
        exporter.outputURL = exportURL;

        //
        // Delete any existing path in the bundle if one already exists
        //
        NSFileManager *fileManager = [NSFileManager defaultManager];
        if ([fileManager fileExistsAtPath:exportURLPath])
        {
            NSError *error;
            [fileManager removeItemAtPath:exportURLPath error:&error];
            if (error)
            {
                NSLog(@"error deleting file: %@", error.localizedDescription);
            }
        }

        //
        // Export the audio data using the AVAudioExportSession to the
        // exportURL in the application bundle
        //
        [exporter exportAsynchronouslyWithCompletionHandler:^{
            AVAssetExportSessionStatus status = [exporter status];
            switch (status)
            {
                case AVAssetExportSessionStatusCompleted:
                {
                    EZAudioFile *file = [EZAudioFile audioFileWithURL:exportURL];
                    completion(file ,nil);
                    break;
                }
                case AVAssetExportSessionStatusFailed:
                {
                    completion(nil, exporter.error);
                    break;
                }
                default: 
                {
                    NSLog(@"Exporter status not fialed or complete: %ld", status);
                    break;
                }
            }
        }];
    }
    else
    {
        NSError *error = [NSError errorWithDomain:@"com.myapp.sha"
                                             code:404
                                         userInfo:@{ NSLocalizedDescriptionKey : @"Media item's URL not found" }];
        completion(nil, error);
    }
}

Usage:

//
// Get an EZAudioFile from the first valid MPMediaItem (meaning it has a URL)
// from the user's iPod library
//
MPMediaQuery *everything = [[MPMediaQuery alloc] init];
MPMediaItem *song = [[everything items] firstObject];
[self openMediaItem:song
         completion:^(EZAudioFile *audioFile,
                      NSError *error)
{
     NSLog(@"audio file: %@, error: %@", audioFile, error);
}];

I could build this into the EZAudioFile, but it would require including the MediaPlayer API as a dependency for EZAudio on iOS devices. Anyone feel strongly that this should be integrated directly into EZAudio?

@syedhali
Copy link
Owner

syedhali commented Jul 3, 2015

Going to close this ticket for now

@syedhali syedhali closed this as completed Jul 3, 2015
@solomon23
Copy link

ipod-library urls were working in 0.0.6 but I just upgraded to 1.1.1 and it stopped working. I am now required to do the above ? What I'm seeing is the EZAudioFile dealloc as soon as i create it and crash on dealloc with: "Error: Failed to dispose of ext audio file (-50)"

@superuzoma
Copy link

@solomon23 Were you able to find a solution to this?

@solomon23
Copy link

Yea:

master...solomon23:remove-file-check

On Wed, Dec 9, 2015 at 6:13 PM, Uzoma Orji notifications@github.com wrote:

@solomon23 https://github.com/solomon23 Were you able to find a
solution to this?


Reply to this email directly or view it on GitHub
#12 (comment).

@vinhnguyendinh
Copy link

2016-07-14 16:21:55.911 AppEditMusic[2922:914540] outputs: (
"<EZAudioDevice: 0x157864cc0> { port: <AVAudioSessionPortDescription: 0x15785cc90, type = Speaker; name = Loa ngo\U00e0i; UID = Speaker; selectedDataSource = (null)>, data source: (null) }"
)
2016-07-14 16:21:55.950 AppEditMusic[2922:914540] Error overriding output to the speaker: The operation couldn’t be completed. (OSStatus error -50.)
2016-07-14 16:22:36.548 AppEditMusic[2922:914540] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSURL initFileURLWithPath:]: nil string parameter'

@saitjr
Copy link

saitjr commented Jul 14, 2016

You have to copy item from iPod library to sandbox.
Checkout: https://github.com/jasonsaw/TSLibraryImport

@vinhnguyendinh
Copy link

Thank you very much ! :)

2016-07-14 16:43 GMT+07:00 saitjr notifications@github.com:

You have to copy item from iPod library to sandbox.
Checkout: https://github.com/jasonsaw/TSLibraryImport


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#12 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/ANJRvGRLVbsBWjhS6TAfb6L8EoE8E2Xiks5qVgTdgaJpZM4BZHDL
.

@schardt
Copy link

schardt commented Oct 13, 2016

Syed, I'm just starting with EZAudioPlayer. Is it still the case that one must copy an iPod Library song into the Documents folder before playing it with this class? If so, how are you and other users handling the case where two songs have the same title? (I suppose one could use the songs' IDs but wondering if you have something better.)

How long does it take, in your experience, for an iPhone 5s to copy a 5min song? Is it as quick as a raw file duplication?

A couple of people in this thread have noted that EZAudio DID play iPod URLs in an early version. Did you ever check out whether this is true and perhaps how you can get this functionality back?

Also, someone noted that playing iPod URLs works in iOS 7+ but not in 6. It seems that can't be true, but just wondering.

Basically, I'm trying to avoid copying files like this. It's a fuss to either keep track of which files have been copied and/or when to delete them.

Thanks so much for making this library! I've been using EZMicrophone for years now in an LED display client app called LED Lab. I'm looking forward to using more of the library soon!

@dxclancy
Copy link

dxclancy commented Oct 15, 2016

No, it is not necessary to copy the files, you should be able to play them directly, but you need to make a small few changes to some of the error handling in the library. There is an issue in the library when validating the url. You should be able to search other issues for the things that need to be changed.

I believe this is the issue in EZAudioFile:

    // dxc add:
    [EZAudioUtilities checkResult:ExtAudioFileOpenURL(url, &self.info->extAudioFileRef)
                        operation:"Failed to create ExtAudioFileRef"];

    // dxc: removed
    //NSURL *fileURL = (__bridge NSURL *)(url);
    //BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:fileURL.path];
    //
    ////
    //// Create an ExtAudioFileRef for the file handle
    ////
    //if (fileExists)
    //{
    //    [EZAudioUtilities checkResult:ExtAudioFileOpenURL(url, &self.info->extAudioFileRef)
    //                        operation:"Failed to create ExtAudioFileRef"];
    //}
    //else
    //{
    //    return NO;
    //}

@schardt
Copy link

schardt commented Oct 17, 2016

Thanks dxclancy! Yes, MPMediaItem's URLs are useable by EZAudioFile, once you take out the "fileExistsAtPath" call. I ended up tweaking a LOT of code in EZAudio. There were a number of loose ends and things that imagine would sometimes crash. (eg: Changing the length of buffers in an AudioBufferList.) Things are working REALLY well in LED Lab now!

@xuzhongping
Copy link

@dxclancy thankyou , use your code, has solved my problem!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests