salsaman / LiVES

LiVES is a feature rich application which combines elements of VJ and video editing software. The current version runs on Linux / BSD. Check_out_the_new_discussion_area https://github.com/salsaman/LiVES/discussions
http://lives-video.com
GNU General Public License v3.0
89 stars 11 forks source link

Lives tries to start JACK instead of connecting to it #28

Open yurivict opened 3 years ago

yurivict commented 3 years ago

image

It should connect to an already running JACK server, or at least offer such option.

Also it seems to suggest that ALSA is required for JACK, which is wrong. JACK can work through OSS too. Please correct this message.

Also it should report the reason why JACK failed to start. Did some command or system call fail?

salsaman commented 3 years ago

Thank you for the bug report. There are two ways to fix this in general usage, you can either start lives with the -jackopts option (lives -help will show the format of the option value) or else you can go into Tools / Preferences / Jack integration and make sure the options to start jack transport server and start jack audio server are both unchecked.

However I am guessing you got this on a fresh install so it makes sense to offer the option to start the server or not at that point too. But in that case, if the server is not started before starting LiVES then you will also get an error that it was unable to connect.

I guess a better solution might be to offer an "auto" option, where it first tries to connect to a running server, and if it cant then it tries to start the server itself.

The reason it is showing "alsa" in the error dialog is that "alsa" is hardcoded as the default driver name (except for SOLARIS which uses "oss" and DARWIN which uses "coreaudio", and the mingw version will use "portaudio" IIRC). If you were running LiVES from a terminal you would likely see the error "Could not find a suitable driver for jack" (it is also a break point if running in developer mode, (i.e set "Enable developer options" from the Help menu). I guess it is still a bit cryptic though.

All of this is really a hang over from earlier days before jackcontrol was integrated into the code. Prior to that, it was necessary to use or to create a ~/.jackdrc file with the driver name hardcoded.

So I think the best thing now would be to display the list of drivers the first time that a connection is made to the server and allow the user to select one from the list.

Then there are a few further complications:

So then there should be a further option still - use this driver when starting jack, force this driver even when jack is running, and use jackdrc file.

LiVES actually creates 3 clients for jack - a transport client, an audio writer client and an audio reader (for external audio mode). The idea was that it should be possible to use two different jack servers, one for transport and the other for audio. This is only half implemented, there is some support for this in the code but right now transport and audio use the same server ("default"). So it would be nice to separate these more and allow setting of the server names and returning to the matter in hand, then it would be necessary to allow selection of two drivers and servers, one pair for for transport and one pair for audio,

And here it gets a little tricky because then it could be set up to use 2 different servers and in the case that the user only starts one, then do we create a second server, or ignore the server name settings and connect all clients to the running server ?

Finally, there are also 2 driver types, master drivers and slave drivers. There must be exactly one master driver per server, but there can be any number of slaves (e.g. MIDI). This also needs to be accounted for.

So - I will make a start on this and maybe implement things in stages, so that I can get a better idea of how all of these pieces will fit together. If you have any ideas or suggestions about the items I mentioned, please fell free to add additional comments.

salsaman commented 3 years ago

First of all I I adjusted the initial install so that it will always show the audio selection window, even if only one choice of audio player is available Screenshot_2021-02-19_00-13-44

Then if jack is selected, the initial start mode needs to be selected Screenshot_2021-02-19_00-10-56

Then if "Start Server" is selected, a message will pop up, informing the user they should manually start jack if it is not yet running,

salsaman commented 3 years ago

Adding new bits to jackopts, I think this should work:

Screenshot_2021-02-19_01-04-35

salsaman commented 3 years ago

Yes, 'auto' connection mode works very nicely !

salsaman commented 3 years ago

Now I remember why I built in that separation into transport and audio servers. It is to allow for advance usage, for example the possibility of using jack with a dummy driver as a transport controller whilst using a separate audio player (e.g pulseaudio) as the audio server.

I guess also if you are not using alsa then none of the MIDI functions will work, so as part of this overhaul I should look into using jack MIDI.

And additionally, I did some development of a 'null' audio player, which allows LiVES to be used with no audio drivers. It is not fully ready yet, it needs to keep track of the "fake" audio position so that things like looping still function correctly, but with a bit more work it could be offered as an "experimental" option. In fact it is already possible if you start lives with -aplayer none.

salsaman commented 3 years ago

Updated prefs tab; the "Configure Server and Driver Buttons" are currently just placeholders Screenshot_2021-02-19_17-56-34

Server connection mode is new, as well as Enable / Disable Transport.

salsaman commented 3 years ago

Actually, now I have dug a bit deeper, having the connection mode no longer makes sense.

Instead it is better to have two binary options:

Then if transport client is enabled, then its server will be auto started when LiVES starts up, or when transport client is enabled in Preferences (unless it is also audio which is running).

If audio server is enabled, then that will also be auto started when the program starts up, unless transport already started it, in which case it will just connect the client.

Note: there is a conflict here if both clients (transport and audio) use the same server but different clients, (e.g transport uses 'dummy' and audio uses 'OSS') so this needs to be handled - in this case the audio server takes precedence.

If auto shutdown is enabled, then when LiVES exits, first the audio server will be stopped if it is running, then the transport server (unless both servers are the same). If audio player is changed in Prefs. then we will shutdown audio server, unless it is also the active transport server. Likewise if transport client is disabled in Prefs we should shut down the transport server unless it is also the active audio server.

There is another conflict here if transport and audio both use the same server and one is set to auto shutdown and the other not. I think this would be best handled by warning the user and forcing them to change the settings.

And another situation to be avoided - if the user sets audio server to auto start and transport server to not auto start. Then it could fail trying to connect the transport client.

So actually the best way to do this is - if transport and audio use the same server, then the two sets of settings are locked together so setting one changes both.

Then if transport and audio are set to use different jack servers then the other settings can be unlocked, and if the two servers are set identical then whichever server name was changed will then be locked with the settings from the other server.

For now this a moot point because at this point both servers have to be "default".

One more difficulty - one client is set use a config file, the other uses internal settings, or both are set to use different config files. So for the present, both transport and audio will be constrained to both use the same config file or both use internal settings. I think the solution would involve something like parsing the config file and extracting the server name and other settings and checking for conflicts.

salsaman commented 3 years ago

I think additionally, shutting down the server on exit only makes sense if LiVES also started that server. It would be strange and probably annoying if LiVES connected to an already running server and then killed when it exited.

yurivict commented 3 years ago

It should normally be impossible for user apps to start servers. For example, on FreeBSD:

$ service jackd start
Starting jackd.
eval: cannot create /var/log/jackd.log: Permission denied
rtprio: RTP_SET: Operation not permitted

service jackd start only succeeds as root. This is how it should be.

salsaman commented 3 years ago

LiVES uses jackctl_server_start(), the log file will not be created and it will not use rtp.

salsaman commented 3 years ago

If it fails to start the server it will show an error dialog, and exit, and the preferences to start jack at startup will be disabled, as you saw yourself.

salsaman commented 3 years ago

Then on restart it will try to connect to a running instance, if it fails this time it will show a different error, "unable to connect to jack server, please start jack before starting LiVES"

salsaman commented 3 years ago

Some of this is not so user friendly, because in the past it was mainly used by Linux users, and in that environment, most users would be using pulseaudio, whereas jack is mainly used by more tech savvy individuals. But it is a different situation in FreeBSD, because there is no pulseaudio, and jack is used by all users as far as I can tell.

Also in Linux, OSS is almost never used these days...first it was pretty much replaced by ALSA, and then by pulse.

salsaman commented 3 years ago

jack was around before pulse, it was actually developed for Ardour, I am not sure if you are aware of that. But it was only ever really intended for precision audio work, for example the latency demands are very exacting, if a client delays too long returning audio, the client can be dropped "zombified" by the server and this can happen very easily with LiVES since it is highly multithreaded and having to deal with video and effects and so on. Pulseaudio is more forgiving with latencies, it won't drop any clients, so unless you have a system which is specifically tuned for real time performance then it is a better choice for general applications.

salsaman commented 3 years ago

If you are running jack in realtime mode, as it seems to be the case then it is even more demanding, in fact if you notice that LiVES is being dropped by the jack server, then you should start jackd with the -t option and gradually increase the value until that stops happening. (Actually it might not be so bad now, the timeout default is now 500 mSec, which should be OK in most situations, in older versions the default was lower, I think about 40mSec) also LiVES is much more optimised these days so having said all that it might not be a problem any more.

salsaman commented 3 years ago

Anyway, returning to the original issue, it seems like LiVES may have been able to create the jack server, but the problem occured because it was selecting a non existent driver (alsa), so it will be interesting to see it can work. As a quick test you could just edit src/jack.h and change

ifndef IS_DARWIN

...

and then recompile it and run lives with commandline option -jackopts 16

It would be interesting to see if it succeeds in creating a jack instance or not.

yurivict commented 3 years ago

But it is a different situation in FreeBSD, because there is no pulseaudio, and jack is used by all users as far as I can tell.

PulseAudio exists on FreeBSD and is used by most desktop users.

Both PulseAudio and Jack audio servers can run simultaneously without any problems. Additionally OSS, PortAudio and some other audio interfaces can be used at the same time.

salsaman commented 3 years ago

Ah good to know that pulseaudio does exist there. It seems like I was given misleading information, or I misunderstood. I am aware that there is support for running pulse and jack simultaneously but the last time I tried it was buggy and hard to set up. Things may have improved now, but I generally found it to be more hassle than just switching between one or the other.

yurivict commented 3 years ago

[...] I generally found it to be more hassle than just switching between one or the other.

From the application perspective - zero hassle. Just stop using one interface and begin using the other interface.

Maybe Linuxes have buggy audio - I don't know because I don't use them.

salsaman commented 3 years ago

This is what users will see now the first time LiVES needs to connect to jack. In your case it would show 'oss' instead of 'alsa' and you would thus be able to choose that option.

Screenshot_2021-02-20_02-55-24

salsaman commented 3 years ago

This comes after the setup phase, and if I had chosen then NOT to auto connect then I would have got an error message instead.

If the startup and connection attempt fails here, then the result is as before, an error will be shown, auto start will be disabled and the program will exit,

Instead of exiting, in the near future the user will be able to choose to continue with no audio (null audio [player) once that has been tested more thoroughly.

salsaman commented 3 years ago

OK, so the basic parts of the reworking are now in place. A few things are still missing, namely:

Anyway, the code that is there should now be quite usable; it is possible to select the 'oss' driver the first time the server is started. Or if preferred, just start LiVES with a running jackd with the name 'default' and LiVES will connect to it automatically now.

On a fresh install users will see this if they pick jack as the audio player: Screenshot_2021-02-20_20-14-25

The checkbutton at the top selects whether LiVES will try to start a jack server if it is unable to connect to a running instance.

Then below this you can choose either to start the server using a config file, or using predefined settings. You can browse to a config file (I need to figure out how to pass that to the server), maybe just running the config file as a shell script. Then below that, just the server name can be changed at this point, this is only relevant if a config file is not used.

LiVES will then attempt to connect the audio client (the transport client is now disabled by default at install time, and has to be purposely enabled later in Prefs). If the connection works then great. Otherwise, depending on the settings, it will either error and exit or try to start the audio server itself.

If startup with config file was chosen, that will be tried, If on the other hand using internal settings was picked then: Since this is the first connection, now a list of drivers is pulled from the jack server and presented similarly to this:

Screenshot_2021-02-20_20-26-25

Here you can see the list of Master and Slave drivers (this is in jack2, there is a problem with jack1 that it provides no way to distinguish between Master and Slave drivers).

Screenshot_2021-02-20_20-33-20

Clicking on config will fetch the parameters and LiVES is sophisticated enough to easily convert between parameter types and generate an interface window like this

There is also a "Retry Connection" button so there is an opportunity to start jackd manually and connect to it.

Assuming the connection succeeds then if a server was started by the app, the driver details will be saved for future sessions.

Then finally the user can go into Preferences and fully configure the jack options there

Screenshot_2021-02-20_20-40-43

This tab has been completely redesigned. There is now a checkbutton to enable jack transport client (off by default). Both clients (transport and audio) now have checks for auto startup / auto shutdown (shutdown an only be set if auto startup is enabled). Both sets of settings are locked in sync. And the last thing, each server has a button for Server / Driver config. For now the transport button will be non functional, but clicking on Audio client button, it will be similar to the windows shown earlier, the user will be able to choose again whether to use internal settings or a config file for server startup, as well as setting the server name (with the possibility of setting different server names for connection and for startup, e.g try to connect to "default", if that fails the start up a server with the name "local"...) and here it will also be possible to change / configure the drivers (master and slaves), a feature of this will be that the current settings will be backed up, and should LiVES fail to start with the new settings then it will automatically revert to the old settings.

What seemed like a simple fix has actually been quite complex to get right. I wasn't happy with hardcoded values like the driver and server settings and empowering users to have more control of the setup seems like something that needed to be done. I will finish up the remaining items on the TODO list and then these upgrades will be just in time for the next release.

Any feedback, suggestions, criticisms are welcome. If possible it would be great if others could test this and make sure it is all functioning on a variety of systems. A fresh install can be triggered simply by deleting the ~/.config/lives directory before starting the app.

salsaman commented 3 years ago

Still working on this, I have not forgotten ! Got a bit sidetracked because I needed to install LiVES on a new machine and I noted a few bugs in the Setup process and so decided to fix those, as it tied in quite nicely with this Plus I had some new ideas in unrelated ideas which I wanted to test out. The rewrite of the jack setup is coming along nicely anyhow.

Error messages are now more logical, with different versions being displayed depending on whether the failure was trying to connect to a running server or trying to start up an own one.

If the client is set to only connect then there is no need to choose a driver any more, so OSS should work out of the box. If the client is set to start a server if it cannot connect, then it will try to do so, and prompt for the driver, as shown above.

It is now possible to view a status log for the clients, this can be done currently via Preferences / Jack Integration, but there should be a menu option to show this also. The status log looks like this:

Screenshot_2021-03-10_00-32-21

I'll maybe add a bit more info to that, like the server audio rate.

I think the only remaining thing now is the 'advanced configuration' for servers and drivers. Furthermore, I already did the code for showing the interface windows created from the parameters which can be obtained by querying them, so actually all that is left is to store the parameter settings between sessions, and pass those parameters to driver and server. I guess it is pretty much expert functionality, and only applies if starting a server without the use of a config script. But for example, one can enable or disable real time support for the server this way.

Once all that is done, I plan to retest all of the transport functions.

Anyhow, the original issue should noe be fixed. I'll keep the bugreport open a little longer if I may, as it is useful to record all of the related activity that fixing the bug inspired.