iOS media library


#1

As it’s possible to access the iOS media library (i.e., songs) especially in 4.2 and later I’ve been playing with getting this to work in Juce. The only problem is that I think it requires us to use Apple’s MPMediaPickerController to navigate the library. There are a few other features that can only be accessed (legitimately) via Apple dialogs (e.g., the cameras) so it would be useful to allow native view controllers to appear over Juce ones and then be dismissed to return to the Juce interface.

I’ve managed to hack it to access the main view controller via the first responder and popup the MPMediaPickerController then return to the Juce interface. There are two issues

  1. If the Juce main window isn’t fullscreen as the MPMediaPickerController is popped up when the Juce interface returns it has been scaled up to fullscreen (not really an issue as a real app would probably have the window fullscreen anyway).
  2. Occassionally the MPMediaPickerController can’t be intefaced with (except for its cancel button) - I’m curious why this this - it fails to get focus.

Anyway here’s the code so far:

MainComponent.h

[code]#ifndef MAINCOMPONENT_H_9E9C97F1
#define MAINCOMPONENT_H_9E9C97F1

#include “…/JuceLibraryCode/JuceHeader.h”

class MainComponent : public Component,
public ButtonListener
{
private:
TextButton* button;
void* voidPeer;

public:
MainComponent();
~MainComponent();
void resized();
void buttonClicked(Button* theButton);
void itemSelected(void* item);
void userCancelled();
};

#endif // MAINCOMPONENT_H_9E9C97F1[/code]

MainComponent.mm

[code]#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>

#include “MainComponent.h”

//----------------------------------------------------------------------
@interface MainComponentPeer : NSObject
{
MainComponent* peer;
UIView* view;
UIViewController* vc;
MPMediaItem currentItem;
}
@property (nonatomic) MainComponent
peer;
@property (nonatomic, retain) UIView* view;
@property (nonatomic, retain) MPMediaItem *currentItem;
-(void)showPicker;
@end

//-------------------------------
@implementation MainComponentPeer
@synthesize peer, view, currentItem;

-(void)showPicker
{
id nextResponder = [view nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]])
{
vc = [(UIViewController*)nextResponder retain];

	MPMediaPickerController *picker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeMusic];
	picker.delegate = self;
	picker.prompt = @"Choose song..";
	[vc presentModalViewController:picker animated:YES];
	[picker release];
} 
else 
{
	NSLog(@"error...");
}

}

  • (void)mediaPicker:(MPMediaPickerController*)picker didPickMediaItems:(MPMediaItemCollection*)items
    {
    if([items count] < 1)
    {
    [self mediaPickerDidCancel:picker];
    }
    else
    {
    [vc dismissModalViewControllerAnimated:YES];
    self.currentItem = [[items items] objectAtIndex:0];
    peer->itemSelected(self.currentItem);
    [vc release];
    vc = nil;
    }
    }

  • (void)mediaPickerDidCancel:(MPMediaPickerController *)picker
    {
    [vc dismissModalViewControllerAnimated:YES];
    [vc release];
    vc = nil;
    peer->userCancelled();
    }
    @end

//----------------------------
MainComponent::MainComponent()
{
addAndMakeVisible(button = new TextButton(“Push Me”));
button->addListener(this);
}

MainComponent::~MainComponent()
{
deleteAllChildren();
}

void MainComponent::resized()
{
button->setBounds(10, 10, 100, 20);
}

void MainComponent::buttonClicked(Button* theButton)
{
if(theButton == button)
{
MainComponentPeer* peer = [[MainComponentPeer alloc] init];
peer.peer = this;
peer.view = (UIView*)getPeer()->getNativeHandle();
voidPeer = peer;

	[peer showPicker];
}

}

void MainComponent::itemSelected(void* voiditem)
{
MPMediaItem currentItem = (MPMediaItem)voiditem;
NSString* title = [currentItem valueForProperty:MPMediaItemPropertyTitle];
NSLog(@“title: %@”, title);

MainComponentPeer* peer = (MainComponentPeer*)voidPeer;
[peer release];

}

void MainComponent::userCancelled()
{
MainComponentPeer* peer = (MainComponentPeer*)voidPeer;
[peer release];
}
[/code]