2009-12-28 3 views
9

코코아 스크립팅 브리지를 사용하여 새 사용자 재생 목록을 만들려고하지만 작동하지 않는 것 같습니다. 지금까지이 :스크립팅 브리지로 iTunes 재생 목록을 만듭니다

iTunesBridge [630 : 80F] 나는 시도하고 재생 목록의 이름을 추가하면

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]; 
} 

, 나는 오류 메시지가 도착 *** - [SBProxyByClass에서는 setName을 :] : 개체가 아직 컨테이너에 추가되지 않았습니다. 선택자를 인식하지 못했습니다

올바른 방향으로 나를 가리킬 수 있습니까?

+0

[소스 이름] isEqualToString : @ "Library"]'영어 이외의 시스템에서 테스트 했습니까? 깨지기 쉬운 것 같습니다 ... – Kornel

+1

영어가 아닌 시스템에서는'([source kind] == iTunesESrcLibrary) '를 사용하십시오. – fabian789

답변

5

SB에서 새 응용 프로그램 개체를 만들기가 까다로워졌습니다. pseudo-Cocoa-ish alloc-init-insert 절차는 실제로 밑에있는 것에 닮지 않습니다. alloc-init이 후속 메서드 호출로 조작 할 수있는 일반 객체를 만드는 것처럼 보이지만 결과는 실제로 SI 함수가 '배열'에 '삽입'되는 지점인데, 이때 SB는 실제 make 이벤트를 보냅니다. 대상 프로세스로 SB 비평에 대해서는 herehere을 참조하십시오.

IIRC, 실제로 초기 속성을 지정할 수있는 유일한 점은 -initWithProperties:입니다. 객체가 '삽입'된 후에 설정할 수 있지만 완전히 다른 작업 (생성되는 객체의 초기 상태를 지정하는 대신 이미 존재하는 객체 조작)이므로 조심하지 않으면 쉽게 의도하지 않은 결과가 발생할 수 있습니다 . 여기에 내가 (objc-appscript를 사용하여, ObjC에서 그것을 할 거라고 방법, FWIW을

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 

을 그리고 : 하여간

는 여기에서 이미하지 않는 경우는 일반적으로 새로운 재생 목록을 만들 것입니다 방법이 존재 이는 내가 그렇게 쓴 나는 SB, 답다)를 사용하지 않았을 :.

#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]; 

(objc-appscript의 단점은 당신이 구축해야하고 응용 프로그램 번들에 프레임 워크의 사본을 포함한다는 것이다 혜택을 더 많은 기능을 갖추고 있으며 응용 프로그램 호환성 문제가 적고 모호하지 않습니다. 또한 appscript의 ASTranslate 도구를 사용하여 위 AppleScript에서 Apple 이벤트를 ObjC 구문으로 변환 할 수 있습니다. 참조 및 명령을 구성하는 방법을 알아 내면 매우 편리합니다.

+2

안녕하세요, 감사합니다. 스크립팅 브리지로 작업하는 것은 악몽입니다. objc-appscript는 좋아 보이지만 재생 목록에 파일을 추가하는 것만으로도 지나치다. 나는 함께 일하게 만들었 : playlist = [[[아이튠즈 classForScriptingClass : @ "재생 목록"] 할당] initWithProperties : [NSDictionary]]]]; 포인터 덕분에 –

1

EyeTunes를 살펴보아야합니다. Objective-C를 사용하여 iTunes와 상호 작용할 수있는 오픈 소스 프레임 워크입니다. EyeTunes로 코드를 작성하면 코드가 훨씬 단순 해집니다. [[source name] isEqualToString:@"Library"] 확실히 영어가 아닌 시스템에서 작동하지 않습니다

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

+2

EyeTunes는 ScriptingBridge가하는 것과 똑같은 일을합니다. 버그 수정 및 작은 응용 프로그램 크기를 위해 항상 제 3자를 통해 Apple 방식을 선택했습니다. – jarjar

+2

이것은 OP의 질문에 실제로 대답하지 않습니다. – ray

2

그냥 빠른 노트. 첫 번째 소스 항목이 맨 위에있는 항목이므로 (예 : iTunesSource *library = [[_iTunes sources] objectAtIndex: 0];) 단순히 사용하는 것이 좋습니다. 주요 도서관.

9

재생 목록과 같은 스크립팅 브리지 객체가 관련 SBElementArray에 추가 될 때까지 메시지를받을 수 없다는 오류 메시지가 표시되므로 배열에 추가하기 전에 재생 목록에서 속성을 설정하려는 시도가 실패합니다 .

가장 간단한 해결 방법은 다음과 같이 코드의 마지막 두 줄을 다시 정렬 할 수 있습니다 :

// 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]; 
} 

다른 옵션은 다른 답변에 대한 귀하의 의견에 따라 당신이하고 결국 무엇 인 initWithProperties:을 사용하는 것입니다.

+1

이것은 허용 된 대답이어야합니다. – ray

2

이것이 라이브러리를 확실하게 식별하기 위해 수행 한 작업입니다. 나는 그것을 잘못 할 수있다.

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