2009-12-28 6 views
9

Estoy tratando de crear una nueva lista de reproducción de usuario utilizando el puente de secuencias de comandos de cacao, pero parece que no puede hacer que funcione. Que tengo hasta ahora:crear lista de reproducción de iTunes con scripting bridge

iTunesApplication *iTunes = [SBApplication 
          applicationWithBundleIdentifier:@"com.apple.iTunes"]; 
SBElementArray *iSources = [iTunes sources]; 
iTunesSource *library = nil; 
for (iTunesSource *source in iSources) { 
    if ([[source name] isEqualToString:@"Library"]) { 
     library = source; 
     break; 
    } 
} 

// could not find the itunes library 
if (!library) { 
    NSLog(@"Could not connect to the iTunes library"); 
    return; 
} 

// now look for our playlist 
NSString *playlistName = @"new playlist"; 
SBElementArray *playlists = [library userPlaylists]; 
iTunesUserPlaylist *playlist = nil; 
for (iTunesUserPlaylist *thisList in playlists) { 
    if ([[thisList name] isEqualToString:playlistName]) { 
     playlist = thisList; 
     break; 
    } 
} 

// if the playlist was not found, create it 
if (!playlist) { 
    playlist = [[[iTunes classForScriptingClass:@"playlist"] alloc] init]; 
    [playlist setName:playlistName]; 
    [[library userPlaylists] insertObject:playlist atIndex:0]; 
} 

Cuando intento y añadir un nombre para la lista de reproducción, me sale el mensaje de error:

iTunesBridge [630: 80F] *** - [SBProxyByClass setName:] : el objeto aún no se ha agregado a un contenedor; selector no reconocido

¿Alguien puede indicarme la dirección correcta?

+0

'[nombre de fuente] isEqualToString: @" Library "]' ¿ha probado eso en sistemas que no están en inglés? Parece frágil ... – Kornel

+1

En sistemas no ingleses, debe usar '([tipo de fuente] == iTunesESrcLibrary)' – fabian789

Respuesta

5

Hacer nuevos objetos de aplicación es terriblemente ofuscado en SB. El procedimiento pseudo-Cocoa-ish alloc-init-insert no se parece en nada a lo que sucede en realidad debajo. Mientras que alloc-init parece crear un objeto regular que puede manipular con llamadas a métodos posteriores, el resultado es en realidad una corrección cuya única función es "insertarse" en una "matriz", en cuyo punto SB envía un evento real make al proceso objetivo (Consulte también here y here para críticas de SB.)

IIRC, el único punto en el que puede especificar las propiedades iniciales es en -initWithProperties:. Puede configurarlos una vez que el objeto se 'insertó', pero esa es una operación completamente diferente (manipular un objeto que ya existe en lugar de especificar el estado inicial de un objeto que se está creando), por lo que puede tener consecuencias imprevistas si no tiene cuidado .

En cualquier caso, aquí es como que normalmente crea una nueva lista de reproducción si no existe ya:

set playlistName to "new playlist" 
tell application "iTunes" 
    if not (exists playlist playlistName) then 
     make new playlist with properties {name:playlistName} 
    end if 
end tell 

Y, Fwiw, así es como lo haría en ObjC, utilizando objc-appscript (que escribí para no tener que usar SB, naturalmente):.

#import "ITGlue/ITGlue.h" 

NSString *playlistName = @"new playlist"; 

ITApplication *itunes = [ITApplication applicationWithName: @"iTunes"]; 
ITReference *playlist = [[itunes playlists] byName: playlistName]; 

if ([[[playlist exists] send] boolValue]) 
    playlist = [playlist getItem]; 
else 
    playlist = [[[[itunes make] new_: [ITConstant playlist]] 
         withProperties: [NSDictionary dictionaryWithObject: playlistName 
                    forKey: [ITConstant name]]] send]; 

(la desventaja de objc-appscript es que usted tiene que construir e incrustar una copia del marco en su paquete de aplicaciones los beneficios es que es más capaz, menos propenso a problemas de compatibilidad de aplicaciones y mucho menos ofuscado. Además, puede usar la herramienta ASTranslate de appscript para convertir los eventos de Apple enviados por el AppleScript anterior en sintaxis ObjC, muy útil cuando descubra cómo construir sus referencias y comandos.

+2

hey gracias, tienes razón, trabajar con scripting bridge es un poco una pesadilla. objc-appscript se ve bien, pero un poco exagerado en mi caso, ya que lo único que estoy buscando es agregar archivos a una lista de reproducción. lo conseguí trabajando con: playlist = [[[iTunes classForScriptingClass: @ "playlist"] alloc] initWithProperties: [NSDictionary blah]]]; así que gracias por el puntero –

1

Debería mirar EyeTunes. Es un marco de código abierto para interactuar con iTunes utilizando Objective-C. Tu código se vería mucho más simple si lo hicieras a través de EyeTunes.

http://www.liquidx.net/eyetunes/

+2

EyeTunes está haciendo exactamente lo mismo que ScriptingBridge. Siempre elige la forma de Apple en lugar de la de terceros, para corregir errores y para un tamaño de aplicación más pequeño. – jarjar

+2

Esto realmente no responde la pregunta de OP. – ray

2

Sólo una pequeña nota que [[source name] isEqualToString:@"Library"] definitivamente no funciona en sistemas no están en inglés. Podría ser mejor simplemente usar iTunesSource *library = [[_iTunes sources] objectAtIndex: 0]; ya que el primer elemento fuente es el que está en la parte superior, p. la biblioteca principal.

9

El mensaje de error indica que los objetos de Scripting Bridge como su lista de reproducción no pueden recibir mensajes hasta que se hayan agregado al SBElementArray correspondiente, por lo que su intento de establecer una propiedad en la lista de reproducción antes de agregarlo a la matriz falla .

La solución más simple es sólo para reorganizar las dos últimas líneas de código, así:

// if the playlist was not found, create it 
if (!playlist) { 
    playlist = [[[iTunes classForScriptingClass:@"playlist"] alloc] init]; 
    [[library userPlaylists] insertObject:playlist atIndex:0]; 
    [playlist setName:playlistName]; 
} 

La otra opción es utilizar initWithProperties: que de acuerdo con su comentario en otra respuesta es lo que terminó haciendo.

+1

Esta debería ser la respuesta aceptada. – ray

2

Esto es lo que he hecho para identificar de manera confiable la biblioteca. Podría estar haciendo mal.

- (iTunesSource *)iTunesLibrary 
{ 
    NSArray *librarySource = [[[self iTunes] sources] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"kind == %@", [NSAppleEventDescriptor descriptorWithTypeCode:iTunesESrcLibrary]]]; 
    if ([[librarySource lastObject] exists]) { 
    return [librarySource lastObject]; 
    } 
    return nil; 
} 
Cuestiones relacionadas