1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

iTunes im Notification Center – mit Album Cover!

Dieses Thema im Forum "Scripting und Automatisierung" wurde erstellt von Pill, 22.08.2012.

  1. Pill

    Pill Thread Starter MacUser Mitglied

    Registriert seit:
    21.02.2011
    Beiträge:
    3.245
    Zustimmungen:
    448
    [​IMG]

    Seit Erscheinen von OS X Mountain Lion und dem Notification Center sind einige Tools (viele davon basieren auf AppleScript) erschienen, die den aktuellen Titel von iTunes anzeigen. Alle scheitern aber bisher daran, das Album Cover anzuzeigen. Das hat einen einfachen Grund: Es ist nicht vorgesehen, dass beliebige Bilder angezeigt werden, sondern es wird immer das Icon des jeweiligen Programms angezeigt. Die einzige Möglichkeit das Album Cover anzuzeigen ist es also das Icon zu ändern. Das ist in AppleScript relativ einfach zu lösen, schnell taucht jedoch ein weiteres Problem auf: Ist ein Programm einmal im Notification Center registriert, wird das Programmicon nicht mehr aktualisiert. Da es keine Möglichkeit gibt per AppleScript ein Programm aus dem Notification Center zu löschen, muss dies manuell in einer SQL-Datenbank geschehen, die sich im Ordner ~/Library/Application Support/NotificationCenter/ befindet.

    Wie ihr schon seht, ist das ganze keine sehr saubere Lösung, eine andere habe ich bisher allerdings nicht gefunden. Die Meldung wird übrigens über Cocoa-AppleScript abgesetzt, vielen Dank an dieser Stelle an kermitd, der das ganze hier beschrieben hat.

    Kommen wir zum Eingemachten, dem Quellcode:

    Code:
    [FONT=Verdana][size=2][color=#4C4D4D]-- main.scpt[/color]
    [color=#4C4D4D]-- Cocoa-AppleScript Applet[/color]
    [color=#4C4D4D]--[/color]
    [color=#4C4D4D]-- Copyright 2011 {Your Company}. All rights reserved.[/color]
    
    [color=#4C4D4D]-- This is the main script for a Cocoa-AppleScript Applet.[/color]
    [color=#4C4D4D]-- You can put the usual script applet handlers here.[/color]
    
    [b]set[/b] [color=#3F7F00]dnc[/color] [b]to[/b] [color=#4A1E7F]current application[/color]'s [color=#3F7F00]NSDistributedNotificationCenter[/color]'s [color=#3F7F00]defaultCenter[/color]
    [b]tell[/b] [color=#3F7F00]dnc[/color] [b]to[/b] [color=#3F7F00]addObserver_selector_name_object_[/color]([b]me[/b], "updateTrackInfo", "com.apple.iTunes.playerInfo", [color=#0000FF][i]missing value[/i][/color])
    
    [b]global[/b] [color=#3F7F00]currentTrack[/color], [color=#3F7F00]currentTrackName[/color], [color=#3F7F00]currentTrackAlbum[/color], [color=#3F7F00]currentTrackArtist[/color][color=#7F007F]
    [/color]
    [b]on[/b] [color=#3F7F00]updateTrackInfo[/color]()
    	[b]tell[/b] [color=#0000FF][i]application[/i][/color] "iTunes"
    		[b]if[/b] [color=#6C04D4]player state[/color] [b]is[/b] [b]not[/b] [color=#4A1E7F]playing[/color] [b]then[/b]
    			[b]return[/b]
    		[b]end[/b] [b]if[/b]
    	[b]end[/b] [b]tell[/b]
    	[color=#3F7F00]fetchiTunesTrackInfo[/color]()
    	[color=#3F7F00]adjustIconForAlbumArtworkOfCurrentTrack[/color]()
    	[color=#3F7F00]sendMessage[/color]([color=#3F7F00]currentTrackName[/color], [color=#3F7F00]currentTrackArtist[/color], [color=#3F7F00]currentTrackAlbum[/color])
    [b]end[/b] [color=#3F7F00]updateTrackInfo[/color]
    
    [b]on[/b] [color=#3F7F00]fetchiTunesTrackInfo[/color]()
    	[b]try[/b]
    		[b]tell[/b] [color=#0000FF][i]application[/i][/color] "iTunes"
    			[b]set[/b] [color=#3F7F00]currentTrack[/color] [b]to[/b] [b]the[/b] [color=#6C04D4]current track[/color]
    			[b]set[/b] [color=#3F7F00]currentTrackName[/color] [b]to[/b] [b]the[/b] [color=#6C04D4]name[/color] [b]of[/b] [b]the[/b] [color=#3F7F00]currentTrack[/color]
    			[b]set[/b] [color=#3F7F00]currentTrackAlbum[/color] [b]to[/b] [b]the[/b] [color=#6C04D4]album[/color] [b]of[/b] [b]the[/b] [color=#3F7F00]currentTrack[/color]
    			[b]set[/b] [color=#3F7F00]currentTrackArtist[/color] [b]to[/b] [b]the[/b] [color=#6C04D4]artist[/color] [b]of[/b] [b]the[/b] [color=#3F7F00]currentTrack[/color]
    		[b]end[/b] [b]tell[/b]
    	[b]end[/b] [b]try[/b]
    [b]end[/b] [color=#3F7F00]fetchiTunesTrackInfo[/color]
    
    [b]on[/b] [color=#3F7F00]adjustIconForAlbumArtworkOfCurrentTrack[/color]()
    	[b]tell[/b] [color=#0000FF][i]application[/i][/color] "iTunes"
    		[color=#0016B0][b]do shell script[/b][/color] "sqlite3 ~/Library/Application\\ Support/NotificationCenter/*.db \"DELETE from app_info where bundleid is 'com.apple.ScriptEditor.id.Now-Playing'\" && killAll NotificationCenter;"
    		[b]set[/b] [color=#3F7F00]thePath[/color] [b]to[/b] (([color=#0016B0][b]path to[/b][/color] [color=#4A1E7F]current application[/color]) [b]as[/b] [color=#0000FF][i]text[/i][/color])
    		[b]set[/b] [color=#3F7F00]thefile[/color] [b]to[/b] ([color=#3F7F00]thePath[/color] & "Contents:Resources:Icon.png" [b]as[/b] [color=#0000FF][i]alias[/i][/color])
    		
    		[b]try[/b]
    			[b]set[/b] [color=#3F7F00]thefilehandle[/color] [b]to[/b] [color=#0016B0][b]open for access[/b][/color] [color=#3F7F00]thefile[/color] [b]with[/b] [color=#0016B0]write permission[/color]
    			[color=#0016B0][b]write[/b][/color] ([b]get[/b] [color=#6C04D4]raw data[/color] [b]of[/b] [color=#0000FF][i]artwork[/i][/color] 1 [b]of[/b] [color=#6C04D4]current track[/color]) [color=#0016B0]to[/color] [color=#3F7F00]thefilehandle[/color] [color=#0016B0]starting at[/color] 0
    			[color=#0016B0][b]close access[/b][/color] [color=#3F7F00]thefilehandle[/color]
    			[b]set[/b] [color=#3F7F00]theCommand[/color] [b]to[/b] "sips --resampleHeightWidth 128 128 " & [color=#6C04D4]quoted form[/color] [b]of[/b] [color=#6C04D4]POSIX path[/color] [b]of[/b] [color=#3F7F00]thefile[/color] & " -o " & [color=#6C04D4]quoted form[/color] [b]of[/b] [color=#6C04D4]POSIX path[/color] [b]of[/b] [color=#3F7F00]thefile[/color] & "; sips -s format icns " & [color=#6C04D4]quoted form[/color] [b]of[/b] [color=#6C04D4]POSIX path[/color] [b]of[/b] [color=#3F7F00]thefile[/color] & " -o '" & [color=#6C04D4]POSIX path[/color] [b]of[/b] [color=#3F7F00]thePath[/color] & "Contents/Resources/Applet.icns';"
    			[color=#0016B0][b]do shell script[/b][/color] [color=#3F7F00]theCommand[/color]
    			
    		[b]on[/b] [b]error[/b] [color=#3F7F00]err[/color]
    			[color=#0016B0][b]close access[/b][/color] [color=#3F7F00]thefilehandle[/color]
    			[b]set[/b] [color=#3F7F00]cmd[/color] [b]to[/b] "rm '" & [color=#6C04D4]POSIX path[/color] [b]of[/b] [color=#3F7F00]thePath[/color] & "Contents/Resources/Applet.icns'; cp '" & [color=#6C04D4]POSIX path[/color] [b]of[/b] [color=#3F7F00]thePath[/color] & "Contents/Resources/Applet2.icns' '" & [color=#6C04D4]POSIX path[/color] [b]of[/b] [color=#3F7F00]thePath[/color] & "Contents/Resources/Applet.icns'"
    			[color=#0016B0][b]do shell script[/b][/color] [color=#3F7F00]cmd[/color]
    			[color=#4C4D4D]--display dialog cmd[/color]
    			[color=#4C4D4D]--tell current application to quit[/color]
    		[b]end[/b] [b]try[/b]
    	[b]end[/b] [b]tell[/b]
    	[b]tell[/b] [color=#0000FF][i]application[/i][/color] "System Events"
    		[b]repeat[/b] [b]until[/b] ([color=#0000FF][b]exists[/b][/color] [color=#0000FF][i]process[/i][/color] "rm") & ([color=#0000FF][b]exists[/b][/color] [color=#0000FF][i]process[/i][/color] "cp") [b]is[/b] {[color=#4A1E7F]false[/color], [color=#4A1E7F]false[/color]}
    			[color=#0016B0][b]delay[/b][/color] 0.1
    		[b]end[/b] [b]repeat[/b]
    	[b]end[/b] [b]tell[/b]
    [b]end[/b] [color=#3F7F00]adjustIconForAlbumArtworkOfCurrentTrack[/color]
    
    [b]on[/b] [color=#3F7F00]sendMessage[/color]([color=#3F7F00]myTitle[/color], [color=#3F7F00]mySubtitle[/color], [color=#3F7F00]myContent[/color])
    	[b]tell[/b] [color=#4A1E7F]current application[/color]'s [color=#3F7F00]NSUserNotification[/color] [b]to[/b] [b]set[/b] [color=#3F7F00]thisNote[/color] [b]to[/b] [color=#3F7F00]alloc[/color]()'s [color=#3F7F00]init[/color]()
    	[b]set[/b] [color=#3F7F00]thisNote[/color]'s [color=#3F7F00]title[/color] [b]to[/b] [color=#3F7F00]myTitle[/color]
    	[b]set[/b] [color=#3F7F00]thisNote[/color]'s [color=#3F7F00]subtitle[/color] [b]to[/b] [color=#3F7F00]mySubtitle[/color]
    	[b]set[/b] [color=#3F7F00]thisNote[/color]'s [color=#3F7F00]informativeText[/color] [b]to[/b] [color=#3F7F00]myContent[/color]
    	[b]tell[/b] [color=#4A1E7F]current application[/color]'s [color=#3F7F00]NSUserNotificationCenter[/color]'s [color=#3F7F00]defaultUserNotificationCenter[/color] [b]to[/b] [color=#3F7F00]deliverNotification_[/color]([color=#3F7F00]thisNote[/color])
    [b]end[/b] [color=#3F7F00]sendMessage[/color][/size][/FONT]

    Da es mit dem Quellcode allein nicht getan ist, gibt es das Programm als ganzes noch hier zum Download. Bedenkt aber, dass sich das Programm noch im Alphastatus befindet. Im Moment kann ich nur garantieren, dass es bei mir funktioniert.

    Natürlich bin ich gespannt auf eure Verbesserungsvorschläge und Anregungen.


    Bildschirmfoto 2012-08-23 um 10.22.56.png

     
    Zuletzt bearbeitet: 23.08.2012
    Pill, 22.08.2012
    #1
    man0l0, tuedel125, Andy.321 und 5 anderen gefällt das.
  2. Pill

    Pill Thread Starter MacUser Mitglied

    Registriert seit:
    21.02.2011
    Beiträge:
    3.245
    Zustimmungen:
    448
    Bekannte Bugs:

    - Cover, die nicht quadratisch sind, werden nicht angezeigt (behoben)
    - Bei Titeln ohne Cover wird das vorherige Cover angezeigt (behoben, das iTunes-Logo wird angezeigt)

    Änderungen:

    - Die Meldungen erscheinen jetzt nicht mehr erst nach 5s, sondern sofort bzw. so früh wie möglich.
    - Trigger über Observer statt Schleife / Performance-Verbesserungen (s. kermitds Vorschlag)
     
    Zuletzt bearbeitet: 23.08.2012
    Pill, 22.08.2012
    #2
  3. Pill

    Pill Thread Starter MacUser Mitglied

    Registriert seit:
    21.02.2011
    Beiträge:
    3.245
    Zustimmungen:
    448
    Noch ein Hinweis: im Moment ist das Skript so eingestellt, dass die Meldung 5s nach Abspielen des Titels kommt (delay 5). Der Wert kann natürlich geändert werden, bei mir reicht ein delay 1 vollkommen aus. Das ist jedoch abhängig von der Geschwindigkeit des Rechners, ich hab das bisher nur bei mir mit SSD ausprobiert. Ich werde aber noch versuchen dafür eine bessere Lösung zu finden.

    Edit: Die aktuelle Version bringt die Meldung nun sobald wie möglich
     
    Zuletzt bearbeitet: 23.08.2012
    Pill, 23.08.2012
    #3
  4. Azathoth

    Azathoth MacUser Mitglied

    Registriert seit:
    20.09.2004
    Beiträge:
    482
    Zustimmungen:
    9
    Geniale Umsetzung! Vielen Dank :)

    Ein kleiner Kritikpunkt nur, bzw. eventuell eine Anregung zur Verbesserung:
    Ich habe bisher die App iTunification verwendet, diese hat aber leider das erwähnte Icon Problem und schaut daher nicht gerade toll aus. Das Einzige was mir daran aber gefallen hat, war dass immer nur der aktuelle Song im Notification Center zu sehen ist und nicht eine lange Liste aller früheren. Wäre sowas auch in deinem Programm machbar?
     
    Azathoth, 23.08.2012
    #4
  5. Pill

    Pill Thread Starter MacUser Mitglied

    Registriert seit:
    21.02.2011
    Beiträge:
    3.245
    Zustimmungen:
    448
    Wenn du in die Systemeinstellungen->Benachrichtigungen gehst, dann kannst du auswählen von keine bis 5 Meldungen.
     
    Pill, 23.08.2012
    #5
  6. kermitd

    kermitd MacUser Mitglied

    Registriert seit:
    16.02.2006
    Beiträge:
    3.551
    Zustimmungen:
    653
    Clevere Lösung! Auch wenn es natürlich (wie Du ja auch schreibst) richtig dreckig ist, ständig das NotificationCenter abzuschießen :D

    Ein erster Verbesserungsvorschlag meinerseits wäre es, kein Polling zu betreiben, sondern Dich für das Empfangen von iTunes-Notifications zu registrieren (erste beiden Zeilen). Dann muss das Skript nicht ständig in einer Schleife nachhaken , sondern wird nur aktiv, wenn iTunes auch wirklich etwas macht.

    Code:
    set dnc to current application's NSDistributedNotificationCenter's defaultCenter
    tell dnc to addObserver_selector_name_object_(me, "updateTrackInfo", "com.apple.iTunes.playerInfo", missing value)
    
    global currentTrack, currentTrackName, currentTrackAlbum, currentTrackArtist
    
    on updateTrackInfo()
    	fetchiTunesTrackInfo()
    	adjustIconForAlbumArtworkOfCurrentTrack()
    	delay 1
    	sendMessage(currentTrackName, currentTrackArtist, currentTrackAlbum)
    end updateTrackInfo
    
    on fetchiTunesTrackInfo()
    	try
    		tell application "iTunes"
    			set currentTrack to the current track
    			set currentTrackName to the name of the currentTrack
    			set currentTrackAlbum to the album of the currentTrack
    			set currentTrackArtist to the artist of the currentTrack
    		end tell
    	end try
    end fetchiTunesTrackInfo
    
    on adjustIconForAlbumArtworkOfCurrentTrack()
    	(*
    		…
    		
    	*)
    end adjustIconForAlbumArtworkOfCurrentTrack
    
    on sendMessage(myTitle, mySubtitle, myContent)
    	(*
    		…
    	*)
    end sendMessage
    
     
    kermitd, 23.08.2012
    #6
    Pill gefällt das.
  7. Pill

    Pill Thread Starter MacUser Mitglied

    Registriert seit:
    21.02.2011
    Beiträge:
    3.245
    Zustimmungen:
    448
    Danke, genau solche Tipps hatte ich mir erhofft!

    Für das Abschießen habe ich leider noch keine Alternative gefunden, es scheint leider keine Möglichkeit zu geben die registrierten Apps im Notification Center zu aktualisieren.
     
    Pill, 23.08.2012
    #7
  8. little_pixel

    little_pixel MacUser Mitglied

    Registriert seit:
    06.06.2006
    Beiträge:
    3.548
    Zustimmungen:
    844
    Hallo,

    Absolut.

    Ergänzend ist noch zu sagen:

    -fetchiTunesTrackInfo kann man komplett weg lassen, da die Notification vom Observer die notwendigen Titelinformationen enthält.
    D.h. man spart sich zusätzlich die gesamte Event Schickerei.

    Viele Grüße
     
    little_pixel, 23.08.2012
    #8
  9. Pill

    Pill Thread Starter MacUser Mitglied

    Registriert seit:
    21.02.2011
    Beiträge:
    3.245
    Zustimmungen:
    448
    Hallo little_pixel,

    da musst du mir nochmal weiterhelfen, wie ich das in ASOC realisiere. Ich schätze mal ich muss folgendes in ASOC umsetzen (?):

    Code:
    - (void)updateTrackInfo:(NSNotification *)aNotification
    {
    /* .... */
    NSDictionary *trackInfos = [[NSDictionary alloc] initWithDictionary:aNotification];
    NSString *currentTrackAlbum = [trackInfos valueForKey:@"Album"];
    /* ... */
    }
    Insbesondere wie ich das Dictionary in ASOC erstelle würde ich gerne wissen. Und falls ich komplett auf dem Holzweg sein sollte, dann brauch ich wohl noch etwas mehr Hilfe ;)
     
    Pill, 23.08.2012
    #9
  10. little_pixel

    little_pixel MacUser Mitglied

    Registriert seit:
    06.06.2006
    Beiträge:
    3.548
    Zustimmungen:
    844
    Hallo,

    vorab, ich habe Null Ahnung von Cocoa-AppleScript. Ich bin in Cocoa/Objective-C zu Hause.

    Der Teil…

    Code:
    me, "updateTrackInfo", "com.apple.iTunes.playerInfo"
    … müßte zu "updateTrackInfo:" werden.

    … und der Teil:

    Code:
    on updateTrackInfo()
    … müßte zu "updateTrackInfo_(notification)" werden.

    Dann müsstest Du Dir von "notification" die Infos abholen und weiter verarbeiten: https://developer.apple.com/library...nsnotification_Class/Reference/Reference.html

    Viele Grüße

    PS:
    Ich habe mir damals aus Neugierde "Cocoa-AppleScript" angesehen, da die Apple Buben ja "AppleScript Studio" eingestampft haben.
    Meiner Meinung nach kann man gleich das richtige "Cocoa/Objective-C" lernen, statt sich "Cocoa-AppleScript" anzutun.
    Den die Ganze Trivialität von AppleScript ist damit verloren gegangen. Um "Cocoa-AppleScript" richtig schreiben zu können sind gute Kenntnisse in "Cocoa/Objective-C" notwendig. … und wer die hat, der macht sich nicht mehr den Umweg.
     
    little_pixel, 23.08.2012
    #10
    chebfarid und Pill gefällt das.
Die Seite wird geladen...