Как прослушать событие запуска приложения в Mac OS X? - PullRequest
2 голосов
/ 29 ноября 2010

Я написал AppleScript для монтирования образа SparseBundle и хочу, чтобы он выполнялся точно при запуске Time Machine.

Сейчас я периодически проверяю, работает ли Time Machine с AppleScript, используя on idle оператор:

on idle
    ....
    return <interval>
end idle

, который не является надежным способом. По моему мнению, лучше было бы добавить триггер для события Application Launch.

Не могли бы вы помочь?

Пример кода Objective-C или Python (я бы предпочел Python) более чем приветствуется.

Ответы [ 3 ]

5 голосов
/ 07 декабря 2010

То, что вы ищете, это NSDistributedNotificationCenter или NSWorkspace , эти классы какао публикуют уведомления о событиях приложения, Для рабочей области, такие как запуск приложений, подключение дисков и т. Д.

Чтобы сделать это в python, вам нужен PyObjC , который в основном является связыванием python для классов Apple по какао.Документация на их веб-сайте немногочисленна, и есть причина, поскольку документация будет в основном такой же, как и документы Apple, поэтому они включают только различия между pyobjc api и API какао.Если вы понимаете, как цель c api преобразуется в python, вы можете идти.Проверьте здесь: http://pyobjc.sourceforge.net/documentation/pyobjc-core/intro.html

Ниже приведен пример, который прослушивает Распределенные уведомления с использованием python.Код ниже в основном добавляет наблюдателя и слушает уведомления itunes.Вы можете следовать аналогичной структуре, но вместо этого добавить наблюдателя для NSWorkspace.Чтобы выяснить, что вы должны слушать, есть приложение, которое будет отображать все уведомления, проходящие через вашу систему.Это называется наблюдатель уведомлений .Используйте это, чтобы понять, что вы должны слушать.Вы также можете преобразовать целевой код c в python.

Что делает код ниже

  1. Определяет новый класс, который наследуется от NSObject, как определено PyObjC
  2. Определяет метод, который получает действительное уведомление и распечатывает его
  3. Создает экземпляр Foundation.NSDistributedNotificationCenter.defaultCenter
  4. Создает экземпляр GetSongs
  5. Регистрирует наблюдателя, передавая ему класс, метод, который вызывается при получении уведомления, и какое приложение и событие следует отслеживать, т. е. «com.apple.iTunes.playerInfo»
  6. Запускает цикл обработки событий,

Одна вещь, которая вас озадачит: доступ к атрибутам (атрибуты target c) не работает так же, как доступ к атрибутам python.т.е. в python вы делаете class_name.att для цели c, в python вы должны вызывать ее как функцию, то есть из моего примера ниже: song.userInfo()

import Foundation
from AppKit import *
from PyObjCTools import AppHelper

class GetSongs(NSObject):
    def getMySongs_(self, song):
        print "song:", song
        song_details = {}
        ui = song.userInfo()
        print 'ui:', ui
        for x in ui:
            song_details[x] = ui.objectForKey_(x)
        print song_details

nc = Foundation.NSDistributedNotificationCenter.defaultCenter()
GetSongs = GetSongs.new()
nc.addObserver_selector_name_object_(GetSongs, 'getMySongs:', 'com.apple.iTunes.playerInfo',None)

NSLog("Listening for new tunes....")
AppHelper.runConsoleEventLoop()

Вот пример фактического вывода ... (ДА БРИТНЕЙ ГОРЯЧИЙ !, НЕ!;)

song NSConcreteNotification 0x104c0a3b0 {name = com.apple.iTunes.playerInfo; object = com.apple.iTunes.player; userInfo = {
    Album = Circus;
    "Album Rating" = 0;
    "Album Rating Computed" = 1;
    Artist = "Britney Spears";
    "Artwork Count" = 1;
    Genre = Pop;
    "Library PersistentID" = 8361352612761174229;
    Location = "file://localhost/Users/izze/Music/iTunes/iTunes%20Music/Britney%20Spears/Circus/02%20Circus.mp3";
    Name = Circus;
    PersistentID = 4028778662306031905;
    "Play Count" = 0;
    "Play Date" = "2010-06-26 08:20:57 +0200";
    "Player State" = Playing;
    "Playlist PersistentID" = 7784218291109903761;
    "Rating Computed" = 1;
    "Skip Count" = 1;
    "Skip Date" = "2010-06-26 12:20:57 +0200";
    "Store URL" = "itms://itunes.com/link?n=Circus&an=Britney%20Spears&pn=Circus";
    "Total Time" = 192444;
    "Track Count" = 16;
    "Track Number" = 2;
}}
ui {
    Album = Circus;
    "Album Rating" = 0;
    "Album Rating Computed" = 1;
    Artist = "Britney Spears";
    "Artwork Count" = 1;
    Genre = Pop;
    "Library PersistentID" = 8361352612761174229;
    Location = "file://localhost/Users/izze/Music/iTunes/iTunes%20Music/Britney%20Spears/Circus/02%20Circus.mp3";
    Name = Circus;
    PersistentID = 4028778662306031905;
    "Play Count" = 0;
    "Play Date" = "2010-06-26 08:20:57 +0200";
    "Player State" = Playing;
    "Playlist PersistentID" = 7784218291109903761;
    "Rating Computed" = 1;
    "Skip Count" = 1;
    "Skip Date" = "2010-06-26 12:20:57 +0200";
    "Store URL" = "itms://itunes.com/link?n=Circus&an=Britney%20Spears&pn=Circus";
    "Total Time" = 192444;
    "Track Count" = 16;
    "Track Number" = 2;
}
{u'Album Rating Computed': 1, u'Album': u'Circus', u'Rating Computed': True, u'Name': u'Circus', u'Artist': u'Britney Spears', u'Track Number': 2, u'Skip Date': 2010-06-26 12:20:57 +0200, u'Library PersistentID': 8361352612761174229L, u'Player State': u'Playing', u'Total Time': 192444L, u'Genre': u'Pop', u'Playlist PersistentID': 7784218291109903761L, u'Album Rating': 0, u'Location': u'file://localhost/Users/izze/Music/iTunes/iTunes%20Music/Britney%20Spears/Circus/02%20Circus.mp3', u'Skip Count': 1, u'Track Count': 16L, u'Artwork Count': 1, u'Play Date': 2010-06-26 08:20:57 +0200, u'PersistentID': 4028778662306031905L, u'Play Count': 0, u'Store URL': u'itms://itunes.com/link?n=Circus&an=Britney%20Spears&pn=Circus'}
3 голосов
/ 02 декабря 2010

Это не слишком сложно сделать в Objc-C.Вы можете получить доступ к уведомлениям для всех приложений через NSWorkspace и NSNotificationCenter.Создайте объект и зарегистрируйте один из его методов для уведомлений типа NSWorkspaceDidTerminateApplicationNotification.Что-то вроде:

@interface NotificationObserver : NSObject { }
- (void) applicationDidLaunch:(NSNotification*)notification;
@end

@implementation NotificationObserver : NSObject
- (void) applicationDidLaunch:(NSNotification*)notification
{
  // Check the notification to see if Time Machine is being launched.
}
@end

void watch(void)
{
  NSNotificationCenter* notificationCenter
    = [[NSWorkspace sharedWorkspace] sharednotificationCenter];
  NotificationObserver* observer = [[NotificationObserver alloc] init];
  [notificationCenter addObserver:observer
                         selector:@selector(applicationDidTerminate:)
                             name:@"NSWorkspaceDidTerminateApplicationNotification"
                           object:nil];
}
0 голосов
/ 06 декабря 2010

Это не ответ на ваш вопрос, но он может решить вашу проблему.

Почему бы просто не запустить Time Machine с помощью AppleScript после монтирования образа диска? Затем, вместо того, чтобы запускать Time Machine напрямую, всегда вызывайте Time Machine через ваш скрипт. Вы даже можете вставить значок Time Machine в файл AppleScript и назвать его «Time Machine», чтобы иллюзия была завершена. : -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...