Ouvrir une application depuis une autre, puis lui adresser des instances d'objets
Herve
Membre
Bonjour,
Je pense que c'est tout bête, mais je ne trouve pas.
Mon idée serait :
- je lance une application depuis une autre avec
- puis je lui envoie des instances d'objet déjà créés
(une instance d'un plug AudioUnit et un entier "int" en l'occurrence, mais peu importe, des objets)
Quelque chose sur le modèle
Ce doit être évident mais les notifications sont internes à l'application et je ne trouve rien d'autre dans la doc.
(J'ai besoin de conserver la méthode
en l'état...)
Je pense que c'est tout bête, mais je ne trouve pas.
Mon idée serait :
- je lance une application depuis une autre avec
<br />
[[NSWorkspace sharedWorkspace] launchApplication:@"MonAppli.app"];<br />
- puis je lui envoie des instances d'objet déjà créés
(une instance d'un plug AudioUnit et un entier "int" en l'occurrence, mais peu importe, des objets)
Quelque chose sur le modèle
<br />
- (BOOL)application:(NSApplication *)application openFile:(NSString *)filename<br />
Ce doit être évident mais les notifications sont internes à l'application et je ne trouve rien d'autre dans la doc.
(J'ai besoin de conserver la méthode
<br />
- (BOOL)application:(NSApplication *)application openFile:(NSString *)filename<br />
en l'état...)
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Si oui, tu peux regarder du côté des Distributed Objects (Programming Guide ici)
Si non, tu peux regarder du côté d'AppleScript pour piloter une application tierce.
Merci pour le lien de la doc que je n'avais effectivement pas trouvé. Je l'épluche et je vous tiens au courant.
Je reviens vers vous suite à ce problème de communication inter-applications.
Voilà ce que je veux faire :
Il y a
- un plug-in Audio Unit
- une application
- un fichier data sur le HD
Lorsque je lance l'application depuis le plug in, je veux que l'application utilise une partie du fichier data avec un index (int)
Pour l'instant je fais :
- dans le plug-in :
et dans l'appli ceci =
Pour l'instant, cela ne communique pas. (le message d'alerte s'affiche)
J'ai essayé aussi avec NSSocketPort depuis le plug-in, mais là ça a planté.
Qu'est-ce que j'oublie, ou que je n'ai pas compris selon vous?
Si c'est juste un seek tu peux faire passer ça par un fichier temporaire... Un plist de config avec chemin du fichier data et settings. Tu passe ce fichier à ton application au lancement au lieux de l'autre.
L'idée est que le fichier data sur le disque dur contient les paramètres du son du synthé. Je veux pouvoir éditer ces paramètres depuis l'application, qui réécrira le fichier. Il doit savoir quel ensemble de paramètres sur les 32 possibles il doit afficher et autoriser la réécriture. Puis l'appli avertira le plug que le travail est fini et qu'il faut recharger le fichier sur disque.
J'ai renoncé à employer le plug comme générateur dans l'appli, cela me semble très incertain. A moins que?
Si c'est juste lire et écrire un fichier ça peut se faire simplement avec du FSEvent ou bien des notification distribués.
C'est à dire ? En quoi utiliser ton plug-in dans ton app est-il compliqué ?
Merci Yoann.
Il semble que FSEvent ne soit pas du Cocoa mais du ... ??
J'ai pensé à un moment intégrer le plug-in ouvert dans le host sequencer dans le AUGraph de l'appli, mais ce que je projette de faire est plus simple.
FSEvent permet de surveiller les changements sur un fichier http://en.wikipedia.org/wiki/FSEvents, soit tu passe par ce type d'outil pour savoir quand le fichier est modifié soit tu utilise une notification inter app.
Je cherche aussi du côté de NSWorkspace. Un truc aussi simple que
avec un int à la place du NSString serait parfait...
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSWorkspace_Class/Reference/Reference.html
Par contre s'il est sûr que son système va lancer l'application, et quand l'application a fini et qu'elle rend la main à son plugin, qu'elle va quitter dans la foulée, là par contre oui ça devrait le faire. Quitte à passer l'option pour lancer une nouvelle instance même si l'appli est déjà lancée.
J'imagine que la fonction dans l'appli doit être quelque chose comme :
Je n'arrive plus à trouver où est référencé
dans la doc en fait... Je ne le trouve ni dans NSApplication ni dans NSWorkspace. La fonction à implémenter doit être à côté?
J'essaie tout cela en tous les cas. Merci encore.
application openFile
J'avais aussi trouvé il y a longtemps cette discussion :
http://forum.cocoacafe.fr/topic/1710-communication-inter-app/page__p__16891__hl__nsconnection__fromsearch__1#entry16891
Connaitriez-vous un bon exemple de code pour NSConnection et NSDistantObject? De toutes façons, pour le message retours, il faudra que je maà®trise les NSConnections...
Merci...
Je sais utiliser les NSNotifications "intra application". Si j'ai bien compris, le NSDistributedNotificationCenter permet la transmission de notifications d'une appli à l'autre à l'intérieur d'un même ordinateur. [/font]
[font=arial,helvetica,sans-serif]Si c'est bien cela, je dois logiquement ajouter une écoute de cettee notification dans le "add listener" de l'application cible :[/font]
[font=arial,helvetica,sans-serif] [/font]
[font=arial,helvetica,sans-serif]et envoyer la requête depuis le plug-in :[/font]
[font=arial,helvetica,sans-serif] [/font]
[font=arial,helvetica,sans-serif]Pour l'instant, la communication ne s'établit pas. Selon vous, où est la faute? (En particulier, je ne sais pas comment dire que l'objet de la notification est un .component. D'habitude, je donne le nom de l'instance de ma classe)[/font]
Cela commence à marcher. Il me faudrait retarder l'envoi de la notification et attendre que l'appli soit ouvert. Je devrais trouver cela dans NSApplication ou son délégué.
Merci à tous encore, je crois que je suis en train de trouver la bonne solution. Comme toujours avec Apple, c'est simple... lorsqu'on connaà®t le truc!
Et en retour, sur réception de cette NSDistributedNotification, le plugin va à son tour envoyer une NSDistributedNotification à l'application pour lui envoyer la ou les infos nécessaires.
C'est effectivement ce que j'ai fait. Cela marche super.
Sauf si j'utilise plusieurs instances de mon plug-in... Faut que j'améliore le truc. Mais je tiens le bon bout.
Ai-je bien compris la doc sur les notifications si je dis que si une "NSDistributedNotification" elle est détruite par défaut? (il y a plusieurs modes de mise en pile des notifications, mais je ne suis pas certain d'avoir compris). De même, il faudrait que si un plug a reçu la notification, les autres l'ignorent.
Je sais que c'est là : la doc mais je ne suis pas certain de tout comprendre!
Ce que j'ai fait marche très bien avec un seul plug-in ouvert, mais lorsque j'en ouvre deux, GarageBand ou LogicAudio plantent (crash) ... mais pas mon appli!!
J'ai fait d'abord :
le plug ouvre l'appli
> l'appli ouverte envoie une NSDistributedNotification
> suite à cette notification le plug crée un NSDictionnary avec un NSNumber et sa clef
> le plug envoie une NSDistributedNotification avec le dico
> l'appli a déjà chargé à l'initialisation un fichier data et affiche le patch correspondant au NSNumber du dico
> ce travail fait, l'appli envoie une NSDistributedNotification et ferme
> le plug recharge le fichier data et joue le son modifié.
Cela marche très bien avec le premier plug mais le second plante tout (le host, pas l'appli). Cela crash lors de la seconde ouverture de l'appli
J'ai essayé de supprimer la première notification, l'utilisateur appuie sur un bouton pour envoyer la notification du plug. Cela crash lorsque l'appli demande aux plugs de recharger le data.
Je mets là le rapport, enfin le début :
Y'a un truc que je ne sais pas. J'aurais aimé que tous les plugs ouverts rechargent le fichier en particulier, est-ce là mon erreur?
Je fais :
Est-ce le "YES" qui pose problème?
(toutes les notifications sont sur ce modèle)
Si quelqu'un voit le "truc", je suis preneur... Merci d'avance!
J'ai essayé :
ou :
pour nettoyer les notifications avant nouveau post, le "EXC_BAD_ACCESS (SIGABRT)" demeure.
J'ai même essyé de reposter dans le plug la notification de l'appli si ce n'était pas à lui de la traiter grâce à un booléen (si oui, le plug la traite, si non il la renvoie) sans succès...
Qu'est-ce que je n'ai pas compris dans les NSDistributedNotifications selon vous?
De mon point de vue, le problème est que lorsque l'appli adresse ses notifications aux divers plug-ins ouvert, le premier concerné est choisi par le NSNotificationCenter comme le récepteur des NSDistributedNotification de l'appli. Les autres du coup sont ignorés.
Mais pourquoi alors ceci :
Exception Type: EXC_BAD_ACCESS (SIGABRT)
Exception Codes: KERN_INVALID_ADDRESS at 0x000000003108e165
Je n'arrive pas à trouver dans la doc la source du problème. Auriez-vous une idée?
Seulement une question par exemple : est-ce que les NSDistributedNotification peuvent être reçues par plusieurs applications? Ou est-ce qu'elles ne peuvent s'adresser qu'à une seule?
En effet, EXC_BAD_ACCESS correspond à l'utilisation d'un espace mémoire qui n'est plus alloué ou ne contient pas ce que tu attends.
Tu utilises une zone mémoire qui n'est pas ou plus allouée, et là où tu t'attends à trouver le début d'un objet, tu tombes sans doute en plein milieu de nulle part.
Or, une des raisons qui font que tu peux avoir cette exception est si tu utilises un objet qui en fait a été désalloué depuis (genre tu as fait un "release" sur l'objet, il a été "dealloc" et détruit, et tu continues à l'utiliser et envoyer des messages à son adresse mémoire après qu'il a été détruit). En activant NSZombiesEnabled, tu vas pouvoir déboguer ça en ne faisant que marquer chaque objet sensé être détruit d'un flag plutôt que de réellement le détruire, et le débogueur saura ensuite te dire "tiens tu essayes d'envoyer un message à une zone mémoire qui contenait avant tel objet, mais qui maintenant n'est plus sensée contenir quoi que ce soit", tu sauras donc quel objet tu as "détruit trop tôt".
Je suis allé dans ton sens, AliGator, mais un peu différemment. Au lieu de mettre les écouteurs automatiquement lors de l'initialisation du plug in, je ne les mets que lorsque j'appelle l'application depuis le plug (launchApp...). De même, je les "remove" lorsque l'application a envoyé sa notification de fin de travail.
Et cette fois, cela ne plante plus!! (essayé avec deux, mais cela devrait marcher avec plus.)
Ouf, et ben, cela a été dur!! /huh.gif' class='bbc_emoticon' alt='???' /> /xd-laugh.gif' class='bbc_emoticon' alt='xd' />