Houston4444 / RaySession

Session manager for linux musical programs
GNU General Public License v2.0
171 stars 20 forks source link

Add a jackpatch display option to RaySession #60

Open newlaurent62 opened 4 years ago

newlaurent62 commented 4 years ago

Hello,

i use Qjackctl to see the jack connections but that adds an application.

Could it be possible to add a jackpatch to the RaySession software ? There could be an option that display only the client connections of the current session ?

This would be very useful when running more than one session.

The jackpatch could let the user switch to the client GUI by clicking on the jack client (in the jackpatch display).

BR, Laurent

Houston4444 commented 4 years ago

Hi !

Could it be possible to add a jackpatch to the RaySession software ?

Of course it is possible, but it's not a little thing. raysession is only a remote for ray-daemon, ray-daemon has no link at all with JACK and this is a good thing (that is the same for non-session-manager and nsmd). I think the patch should be a remote #43 for ray-jackpatch. Personally, I like window containing only the patch (as Catia), because canvas size is bigger when window is maximized.

There could be an option that display only the client connections of the current session ? This would be very useful when running more than one session.

ray-jackpatch doesn't make any difference between connections of ray clients and others. So, having two ray-jackpatch running is a strange thing (both will save all connections). Do you really run two sessions at the same time, I'm interested to know the use case.

newlaurent62 commented 4 years ago

I have not yet use several Raysession at the same time but i face the case when i start some jack applications then i open a Raysession. Jack connections can be a bit tricky when starting with many applications ...

So i though that having a layer in the jack connections could be useful. And this layer could be the RaySession jack client known by ray-jackpatch. I didn't notice that ray-jackpatch does not make any differences between Raysession jack client apps and outside world jack connections. I don't know if this is a good thing or not.

I know Catia, I will give it a try.

May be i could assign a key shortcut to display running instance of Catia and may be it has layer support.

newlaurent62 commented 4 years ago

This script works fine. It switch to Catia window if running otherwise it loads Catia.

#!/bin/bash

if [ "$(wmctrl -l | grep Catia)" != "" ]; then 
  wmctrl -i -a $(wmctrl -l | grep -E ""^.+?\s+.+?\s+.+?\s+Catia$"" | awk '{print $1}') 
else 
  catia
fi

There is canvas in Catia but i don't think there is some sort of Layer. Ideally the layer could be set with a configuration file for use with external applications or by selecting a set of jack clients and give it a name (the layer name).

The user shall be able to zoom on the layer clients only.

newlaurent62 commented 4 years ago

https://github.com/falkTX/Cadence/issues/287

newlaurent62 commented 4 years ago

I have a first implementation of the "go to app" feature in catia.

A context menu appears in Jack client box in catia canvas with all the windows title associated with the jackclient.

I get the window corresponding to each Raysession client from the pid, or from a pid and a regexp. That let it filter on the window title if a process has several windows.

My version of libjack does not implement jack_client_pid function so each Raysession client tells catia its pid and during the load of the Raysession, some metadata on clients are sent to catia.

It would be nice to have a property on ray_control client messages to set and get the client PID that really do the job or has a gui. That would allow to get the pid from ray_control when the jack client is identified to be a Raysession client.

My communication with Catia is very basic and uses files on the system.

Houston4444 commented 4 years ago

Hi ! Having a get_pid for client for ray_control is something easy. To be honest, that is just that I forgot to do this. But I really don't understand what you want with 'set_pid'. I don't think it 's possible to do.

However, with ray_control you can get the daemon pid. And all JACK clients of a ray session are childs of daemon pid. You can read the python method to check this in raysession code src/shared/ray.py line 214 (isPidChildOf).

newlaurent62 commented 4 years ago

currently, in my wizard implementation, i have still a script wrapper that do various check and print debug messages (RAY_SESSION_PATH, RAY_SESSION_NAME, NSM_CLIENT_ID current PWD , command to execute...). It is useful for debugging the raysession document and also to start client that need a different XDG_CONFIG_HOME. The wrapper setup this variable if needed (export XDG_CONFIG_HOME= ...).and starts the "real client". I don't like this way of doing things but i found that it is very helpful for debugging things ...

So i have one indirection ray-proxy does not start the real client but my wrapper script does ...

I thought that my wrapper script would need to tell to ray_control the real client pid and not the wrapper script pid.

Houston4444 commented 4 years ago

Hummm, j'ai pas tout compris, je continue en français pour augmenter mes chances de compréhension.

je vois pas pourquoi tu ne pourrais pas connaître le pid du programme que tu lances par ton script. Le plus simple est évidemment que tu termines ton script par exec mon programme arguments, et dans ce cas le programme est démarré en remplaçant le process du script, et dans ce cas mon_programme à le même pid que le script. L'inconvénient, c'est que tout ce qui sera écrit après cette ligne dans le script sera ignoré.

Jette un coup d'oeil sur le script que j'avais fourni dans ce fil http://linuxmao.org/forumthread95062 , ça pourrait aider. Parce que je vois pas bien ce que ray-daemon pourrait faire d'un set_pid , il arrête les programmes qu'il a démarré c'est tout.

newlaurent62 commented 4 years ago

Merci pour ta patience. Je m'explique.

Je pense que mon script wrapper ne peut pas utiliser exec. Si j'ai bien compris, à l'exécution d'exec, son process fils (le vrai client) remplace le process parent (le script wrapper et devient donc le fils de ray-proxy) et du coup toutes lignes de code après exec ne servent à rien ... Hors, j'ai besoin de récupérer le pid du "vrai client" (le processus fils du script wrapper) pour catia.

catia déduit la fenêtre à afficher en fonction du pid et d'une regexp. Comme ça si il y a plusieurs fenêtres sur un même programme, on peut quand même en sélectionner une grâce à la regexp. ça marche aussi si il y a plusieurs processus d'un même programme vu que la sélection est faîte sur le pid.

Ce serait plus simple si je pouvais récupérer le pid par jack mais la lib que j'utilise me dit que ce n'est pas encore implémenté.

En définitive faire un "ray_control client $clientID set_gui_pid $pid"me permettrait de dire à catia le pid du process qui fournit l'igu car catia pourrait faire un ray_control client $clientID get_gui_pid pour le récupérer. Ce pid serait forcément un sous processus de ray-daemon effectivement (si j'ai bien compris).

Parallèlement à tout ça, je suis conscient que ce script wrapper n'est pas bien mais il me permet en plus de débugger. Il affiche les variables d'environnement plus d'autres variables calculées ainsi que la ligne de commande exécutée et me permet aussi d'affecter une valeur à la variable d'environnement XDG_CONFIG_HOME= ... pour le vrai client (si besoin). Je ne pense pas que je puisse avoir une ligne de commande dans ray-proxy du style "export XDG_CONFIG_HOME=.config monprogramme"

PS: Merci pour le lien sur linuxmao, ce script m'a fait penser à une solution simple pour un autre souci. J'ai un programme qui veut utiliser SIGHUP pour le signal de sauvegarde car SIGUSR1, SIGUSR2 et SIGINT sont déjà pris. Du coup la solution est toute simple, faire un script wrapper qui, quand il reçoit SIGUSR1, envoie SIGHUP au "vrai client" car, si j'ai bien compris, raysession ne gère pas SIGHUP comme un signal de sauvegarde.

Houston4444 commented 4 years ago

Si j'ai bien compris tu veux que ray_control fasse la passerelle d'un process à un autre pour transférer des données. Il est évident que ray_control (plus exactement ray-daemon) ne pourra rien faire de concret avec un set_gui_pid, il est structurellement pas possible du tout que ray-daemon lance un programme en prédéfinissant son pid.

Du coup, je me demande, pourrais-tu sauvegarder les données nécessaires dans un fichier quelque part pour les récupérer ailleurs au besoin ? Sinon, il vaudrait mieux que je fasse une option du genre ray_control client $client_id save_data data_str data_value, et la même chose avec get, mais s'il c'est un pid que tu veux récupérer, ce n'est pas sauvegardable dans le fichier de session (ça change à tous les coups).

si j'ai bien compris, raysession ne gère pas SIGHUP comme un signal de sauvegarde.

En fait il en serait tout à fait capable, c'est juste pour pas surcharger la combobox côté utilisateur qu'il n'y a que None, SIGUSR1, SIGUSR2.

newlaurent62 commented 4 years ago

Du coup, je me demande, pourrais-tu sauvegarder les données nécessaires dans un fichier quelque part pour les récupérer ailleurs au besoin ?

C'est déjà ce qui est fait. J'ai un fichier dans $session_path/default/metadata-clients.yml. Il est créé lors de la création du document raysession.

Sinon, il vaudrait mieux que je fasse une option du genre ray_control client $client_id save_data data_str data_value, et la même chose avec get,

Ce serait bien effectivement. Je distingue deux categories de données:

Si tu pars sur cette solution, ce serait mieux je pense de stocker ces données dans un fichier à part pour que si des modifications malheureuses de ces données sont faîtes cela n'empâche pas la session de s'ouvrir.

Houston4444 commented 4 years ago

Si tu pars sur cette solution, ce serait mieux je pense de stocker ces données dans un fichier à part

Pour le coup c'est pas très pratique. Je vois plus ça comme ça:

pour les données à stocker -> dans le fichier raysession.xml, dans le slot du client Je ne vois pas bien le risque particulier, ray-daemon n'en fera rien sauf évidemment les importer et les réécrire dans le fichier.

pour les données volantes -> dans l'instance Client du ray-daemon tournant. On ne pourra les obtenir et les écrire qu'avec ray_control.

Ça marche pour toi ça ?

newlaurent62 commented 4 years ago

Oui ok.

Pour concrétiser les choses, quel format de commandes proposes-tu avec ray_control ?

newlaurent62 commented 4 years ago

Je vois aussi poindre le besoin de récupérer une liste des sessions ouvertes (port, sessionpath) avec par exemple:

ray_control get_all_session_path_and_port

Si j'ai tout ça, je devrais pouvoir faire communiquer catia avec ray-daemon plutôt que de communiquer par fichiers interposés sur le système.

Houston4444 commented 4 years ago

Pour concrétiser les choses, quel format de commandes proposes-tu avec ray_control ?

Je pensais en interne tout sauver dans 2 dict . Ça donnerait un truc comme : ray_control client CLIENT_ID set_custom_data DATA VALUE ray_control client CLIENT_ID get_custom_data DATA -> VALUE ray_control client CLIENT_ID set_tmp_data DATA VALUE ray_control client CLIENT_ID get_tmp_data DATA -> VALUE

Je vois aussi poindre le besoin de récupérer une liste des sessions ouvertes (port, sessionpath)

Un genre de list à la ls -l en fait. Je regarde ce qu'il est possible de faire.

Houston4444 commented 4 years ago

les custom data c'est fait. J'ai passé 3 fois plus de temps sur comment lire ces p*t de données XML avec QtXml que sur tout le reste. Mais, ouf, c'est bon.

Houston4444 commented 4 years ago

Je vois aussi poindre le besoin de récupérer une liste des sessions ouvertes (port, sessionpath)

En fait quelque part ça m'embête un peu de définir un truc comme ça maintenant qui pourrait être utilisé par des scripts, et que si je veux y ajouter une donnée ça fait foirer tous les scripts. Et puis en fait, tu peux peut-être lire le fichier tmp/RaySession/daemons.xml dans lequel tout est marqué.

newlaurent62 commented 4 years ago

Ok, je vais voir ça. Tu n'as pas déjà une classe qui fait le travail que je peux réutiliser ?

Notes: Y a une erreur dans le nom de l'élément root et inner: /Deamons au lieu de Daemons, pareil pour l'élément interne Deamon au lieu de Daemon.

Houston4444 commented 4 years ago

Oh le boulet ! Ça commence à faire un paquet de fois que je fais cette fote.

Sinon dans src/control/ray_control.py tu devrais pouvoir trouver une classe Daemon (ou Deamon si j'ai fait l'erreur ici aussi ;) ). Mais du coup bon , faut que je corrige l'erreur avant.

newlaurent62 commented 4 years ago

Tu pourrais aussi faire un message avec des champs paramétrables.

Par exemple: ray_control get_info "|" fields port session_path 17810|/home/.../sessionname1 17811|/home/.../sessionname2

comme ça si il faut ajouter des champs, c'est facile à faire et ça ne rend pas le message précédent invalide.

ray_control get_info "|" fields port session_path nsm_url ...

ray_control get_info ? pour obtenir l'ensemble des champs supportés par la commande.

Qu'est-ce que tu en penses ?

newlaurent62 commented 4 years ago

Ok c'est bon. J'ai trouvé ce message:

ray_control list_daemons

ensuite je fais ça:

for port in list_daemons
  ray_control --port port get_session_path

Et ca revient au même que d'avoir un message supplémentaire spécialisé.

Houston4444 commented 4 years ago

Et ca revient au même que d'avoir un message supplémentaire spécialisé.

À quelques millesecondes près quand même, chaque appel à ray_control me coûte environ 50ms, pas réussi à descendre en dessous.

newlaurent62 commented 4 years ago

Comme catia est en python, je peux peut-être utiliser une classe python de RaySession plutôt que de faire des appels système ...

Une idée ?

Houston4444 commented 4 years ago

Le plus rapide en terme de communication, c'est d'implementer un protocol OSC à ton Catia, et là tu parles directement au démon plutôt que de passer par ray_control. Mais à mon humble avis c'est plus long à coder, à voir. Ça dépend de ce que tu souhaites faire.

Si tu souhaite te lancer dans un patchbay adapté à RaySession, je te suggère directement d'entamer le patchbay de RS (si c'est le cas faut qu'on en cause, j'ai ma p'tite idée...).

Sinon tu peux implémenter un protocole NSM à ton Catia, coup de bol, il est en python qt. Du coup tu peux choper src/shared/nsm_client.py (code source RS) et regarder comment c'est foutu avec les signaux par exemple pour le sooperlooper ou le ray-jackpatch.

newlaurent62 commented 4 years ago

Salut,

Je ne pense pas avoir le temps pour me lancer dans l'adaptation de Catia à RaySession.

Le travail que j'ai fait est disponible sur github. git clone https://github.com/newlaurent62/rayZ-builder.git

make test-all

(ça exporte catia et rayZ-builder et les installe sur le système. Ça crée deux sessions dans Ray et dans NSM (Jamulus et simple_example).

Ensuite tu démarres catia et RaySession:

catia raysession

Tu ouvres la session Jamulus et l'autre simple_example, ils se plaidront peut-être que certains programmes sont manquants, tu peux les installer avec:

make prepare-jamulus-ubuntu make prepare-simple_example-ubuntu

et tu pourras naviguer dans catia qui fait le pont entre les clients jack et l'accès aux fenêtres des applications.

Note: les icônes ne s'afficheront pas correctement dans RaySession vu que certains sont dans session-dir/.local/share/icons/32x32 (cf. pull request)

Houston4444 commented 4 years ago

Je ne pense pas avoir le temps pour me lancer dans l'adaptation de Catia à RaySession.

C'était juste au cas où. Tu as raison de ne pas te lancer dans un truc que tu ne peux pas aboutir, c'est un gros chantier.

Pour le reste, je vais tester tout ça quand j'ai un peu de temps. Merci.

Houston4444 commented 4 years ago

mais je peux déjà te dire que ton prénom dans le PREFIX du make ben ça fait foirer le make ;)

newlaurent62 commented 4 years ago

OK y avait aussi d'autres soucis.

La target test-all est testé sur 19.10 et 20.04.

Tu pourras installer les packages nécessaires avec:

make prepare-dev-ubuntu

Ensuite pour installer: RaySession, catia et rayZ-builder:

make test-all

Cependant, les sessions ray créées ne fonctionneront pas car tu n'as certainement pas la même carte son.

Pour créer tes propres sessions:

rayZ_wizards

Sélectionne le type de session cible nsm ou ray (ray par défaut)

Tu pourras choisir ton wizard et le lancer. Une fois cliqué sur finish et avec un peu de chance, cela t'indiquera que la session est créée.

Ensuite démarre raysession et catia.

Houston4444 commented 4 years ago

Salut ! Désolé pour le temps de réponse, malheureusement je n'ai pas de paquet python3-cheetah dispo sur ma distrib (18.04), il est installé avec pip du coup. Mais le make test-all foire pour cause de manque de commande cheetah3

#cp src/package-def/__init__.py build/share/rayZ-builder/session-templates/Jamulus/__init__.py
cp src/wizards/Jamulus/*.wizard src/wizards/Jamulus/pages/*.page build/Jamulus/xml/
test -d src/wizards/Jamulus/snippets && cp src/wizards/Jamulus/snippets/*.tmpl_snippet build/Jamulus/xml/ || exit 0
cheetah3 c -R --nobackup --idir src/wizards/Jamulus/tmpl --odir build/share/rayZ-builder/session-templates/Jamulus/
make[1]: cheetah3: Command not found
Makefile:24: recipe for target 'src/wizards/Jamulus.py' failed
make[1]: *** [src/wizards/Jamulus.py] Error 127
make[1] : on quitte le répertoire « /home/houston/codes_sources/rayZ-builder/test/rayZ-builder »
Makefile:140: recipe for target 'test-all' failed
make: *** [test-all] Error 2
newlaurent62 commented 4 years ago

Salut,

Désolé pour le temps de réponse

Aucun souci.

Le fichier cheetah3 est la version python3 de cheetah et il contient sur ma version d'ubuntu:

/usr/bin/cheetah3

#!/usr/bin/python3
from Cheetah.CheetahWrapper import _cheetah
_cheetah()

Notes: rayZ-builder a surtout été testé sur 20.04 (un peu sur 19.10).

newlaurent62 commented 4 years ago

En tout cas merci pour le temps pris.

Houston4444 commented 4 years ago

problème en voulant lancer catia, il crash:

$ /usr/local/bin/catia 
Traceback (most recent call last):
  File "/usr/local/share/cadence/src/catia.py", line 23, in <module>
    from shared_canvasjack import *
  File "/usr/local/share/cadence/src/shared_canvasjack.py", line 34, in <module>
    import patchcanvas
  File "/usr/local/share/cadence/src/patchcanvas.py", line 42, in <module>
    from properties_helper import GroupPropertiesHelper
  File "/usr/local/share/cadence/src/properties_helper.py", line 9, in <module>
    import jack
ModuleNotFoundError: No module named 'jack'
newlaurent62 commented 4 years ago

Great ! You are close to the test :-)

I removed the dependency.

There is a known bug : when jack server is restarted while catia is running, chances are that the catia synchronization with RaySession stops as well. So you will prefer to first start RaySession and then start catia or start a RaySession that does not restart jack server.

To start the generated RaySessions disable the Jack settings check, go to session-dir/ray-scripts/.env and set USE_JACK_SETTINGS=false

newlaurent62 commented 4 years ago

I was waiting for ray-hack implementation to optimise catia-RaySession synchronization because currently it takes a long time ...

If i remember well, ray-hack allow to use some sort of ray-scripts, is that right ?

for example: load.sh

... print debug information ...
ray_control client $clientID start
... Compute window id ...
newlaurent62 commented 4 years ago

The known bug has been solved.

Houston4444 commented 4 years ago

yes of course, client scripts works also with ray-hack client.

Houston4444 commented 4 years ago

Ok It works, I arrived to load simple_example session, but without jack physical ports in the patchbay (probably because it's not the same as your). Two things I saw : One script user action dialog contains "RaySession" in text, talking about the current session, please use "RaySession" only for the program, preffer "Ray session" or "ray session", or simply "session". During the installation I saw bookmarks appears and disapears in my file manager window, you can avoid this using:

RAY_CONTROL_PORT=$(ray_control start_new_hidden)
export RAY_CONTROL_PORT
# some actions...

ray_control close
ray_control quit

The start_new_hidden option will start a daemon without any option (currently options are: bookmark_session_folder, desktops_memory, snapshots, session_scripts). If needed, you can easily set options with ray_control. The options states of this daemon instance won't be saved.

newlaurent62 commented 4 years ago

Thanks a lot for your remarks. I made the changes.

The problem you raised is that you probably don't have the same software version because you are running a different Linux version.

In order to be fully portable, sessions could use snap, flatpak or AppImage or a docker ? I've heard of these solutions and don't know exactly what are they built for.

What is your opinion ?