On Friday 25 January 2008 18:27:10 Bob Ham wrote:
On Fri, 2008-01-25 at 14:04 +0200, Juuso Alasuutari
wrote:
On Wednesday 23 January 2008 23:21:21 Bob Ham
wrote:
There's no reason to add a system-specific
API layer to LASH itself.
The abstraction could be done by a separate library entirely, eg
libeasyjack.
By "system-specific API layer" do you mean D-Bus?
No, I mean JACK or ALSA or raw1394 or whatever. I'm talking about
something like
lash_easy_jack_client_t *
lash_easy_jack_client(char *client_name,
char *input_port_names[],
char *output_port_names[],
jack_callback_t *cb);
In this case, there's no reason at all to have "lash_" in there.
Why bother with a long-reaching workaround like that? I understood this
hypothetical "libeasyjack" to be something that would enable a program to be
a JACK (libjack) client without actually having to fulfill the requirement of
running with RT priority. But for our needs (setting connections, getting
connection info, etc.) it's simply backwards to stubbornly hold on to keeping
LASH a JACK client. There's a conceptually saner solution around the corner.
The goal of jackdbus has never been to shield applications from JACK's bugs,
and I regret that this conversation has revolved around that side effect for
so long. Jackdbus allows more flexible controlling of JACK settings in a
desktop environment, by desktop applications. Implementing this kind of
interface makes sense for more than one reason.
It's not about "adding a system-specific API layer to LASH", it's about
making
use of an API layer in LASH because it fits the purpose well.
To me, it
seems like overengineering to design the LASH <-> client
protocol with networks in mind. The lashd daemon can use D-Bus to
communicate with clients, but that doesn't mean that several LASH daemons
running on different computers couldn't communicate session events and
data between eachother. The idea would be that all LASH <-> client
connections would be local, but one session could be composed of several
local LASH environments.
The problem here is you then have two communication protocols; one for
local D-Bus communication, and one for inter-host lashd communication.
They're going to be communicating much the same information; client
properties, port names, etc. To have two protocols would be unwieldy.
For domain separation this makes sense. Why add weight to the the LASH <->
client protocol with things such as encryption which most users will never
need?
Don't get me wrong; inter-host communication is a great idea (for future
implementation). But I think a local session protocol should be minimally
burdened by the needs of a minority. Yet this is not the only reason I'm
against a "lashd <-> the entire world" client protocol. Consider the
following:
If your session is spread across multiple networked computers, how will you be
able to auto-launch all the clients if there are no per-host daemons
involved? In other words, your master lashd can launch all the clients on the
master host, but if you also want to launch remote clients you will need some
kind of launcher daemon running on the remote computers.
If there's a lashd running on each computer, the master lashd can tell the
slave lashds to auto-launch their clients. It seems to me that adding this
lashd-to-lashd layer between local domains is both friendlier for clients in
terms of protocol complexity and also enables better control.
But then
again, why should LASH even be concerned with the connections
between clients in the first place?
That's pretty much it's raison d'etre :-) See the following, and note
the file name:
http://teasel.6gnip.net/~rah/why-ladcca.png
OK, I see. :)
There's three different ideas that could be
surmised by "patch system
controller" (at least that I can think of.) There's something like
QJackCtl, which lets users adjust the settings of the patch system like
the sample rate, period size, etc (and we're talking about something
which does it on-the-fly, which doesn't exist yet.) Then there's LASH,
which monitors port connections and manages their automatic reconnection
when a session is restored. Then there's a patch bay, which allows the
user to adjust the connections while a session is active.
There are no inter-dependencies. They all provide distinct sets of
functionality and hence should be separate programs.
LASH is actually two separate sets of functionality in one system:
automatic port reconnection, and non-X11 session management. So, LASH
*does* leave "the other stuff" to a patch system; it leaves it to the
other functionality in itself :-)
It could be the case that the two sets of functionality in LASH can be
separated into different systems but off the top of my head I'm not sure
how inter-dependant they are. Specifically, I'm not sure whether
session management is completely independant of port reconnection, at
least in order to provide LASH functionality.
That reasoning seems solid, thanks for taking the time to explain.
I can imagine how the session could be comprised of:
- LASH which only manages client settings and connections,
- normal LASH clients, and
- a JACK controller, which is basically a normal LASH client.
And I can imagine how the session loading could happen approximately like
this:
- LASH launches the JACK controller app,
- the JACK controller app modifies JACK settings and possibly restarts JACK if
necessary,
- LASH launches the rest of the clients,
- LASH connects the ports between the clients.
I'm still not sure that this would be the most convenient solution for
everyone involved. Would it mean significantly more work for control
application/frontend coders? Would it be more confusing for the users? I'm
hoping that someone could comment on this.
Now imagine the above scenario, but imagine that the JACK controller app
doesn't get launched first. It will potentially wreck the session if it
restarts JACK after other clients have loaded. If controlling JACK settings
is done by one of the session clients, should that client be able to register
to LASH with a special flag which indicates that it should launch first?
Client priorities
Can you explain what you mean by this?
What you were talking about before; dependencies in running order of
clients. Priority is one (simple) way to solve that. Referential
dependencies are a lot trickier. Regardless, the issue needs to be
looked at and that's what this point was referring to.
Good idea, I agree.
Often there are chains of programs that operate on a single "track" (ie,
stereo audio stream.) Eg,
Drums: Hydrogen -> JACK Rack -> Ecasound
Bass: ZynAddSubFx -> Freqtweak -> JACK Rack -> Ecasound
Lead: QSynth -> Ecasound
In the above, each instance of JACK Rack has to have a separate JACK
client name. Most clients append the PID. JACK Rack (and, I assume
others) will let you set the JACK client name from the command-line. So
if you were constructing the about setup, you might execute the JACK
Rack instances like so:
$ jack-rack --string-name Drums &
$ jack-rack --string-name Bass
Which will create two JACK clients named "jack_rack_Drums" and
"jack_rack_Bass".
The purpose of "Track naming" in LASH would be to automate this and
present a convenient interface for setting track names.
I'm not sure that this level of session management is necessary for LASH. But
it may very well be that I'm still not getting the point.
Guaranteed save directory availability
Does this simply mean that lashd will somehow make extra sure that the
directory exists, and that the client can write there? If so, it sounds
good.
Pretty much. At present, in a save operation, clients get told "Save in
$directory" and then the client responds "OK, I've saved there."
With
this kind of protocol, the LASH system isn't providing any guarantee
that the directory will stay there. With programs like Ardour, which
need presistent directories, this a problem.
The solution is to have clients tell the server "I want a persistent
directory" when they start up. The server then tells them, "OK, use
$directory." Then, if the project is moved or closed or whatever, the
server tells the client "Stop using $directory." After the operation is
completed, the client can then be told again "OK, use
$possibly_different_directory."
LASH would only "make sure" that it exists within the LASH system
itself. There are, of course, issues of how to deal with things like
the directory being moved by errant user fiddling, or whatever. FAM may
be able to help with that.
Perhaps lashd could monitor the current save dir via FAM and at least produce
a warning if it gets deleted. But that's more of a tweak than a feature.
How about if a guaranteed directory would be the default? The clients would
receive a directory name (and could also ask for it later if they have a
short memory or something), and it would be guaranteed to exist unless a
special "directory has changed" message has arrived.
Therefore the usual save command wouldn't be "save to $dir", but rather
"save
to the dir that i gave you during init". Only special save commands
like "export all data to $outside_dir" would include the dir name with the
command itself.
"Save big-ass 50M wav file" vs "Save view settings" :-)
I don't get this. But sounds like what's been talked about on #lad: Different
save types like "normal save", "light save", "export"...
>
Networked audio
Handle sessions involving clients on different hosts who communicate
with each other over ports that require reconnecting. Eg, JACK clients
connected using firewire/netjack.
OK, sounds like a reasonable long-term goal.
> User
interface standard
Promote a standard to LASH clients in order to present a consistent user
interface. This would be like the GNOME HIG but audio-specific, eg,
specifying knob widget appearance and behaviour, recommending audio
widget toolkits, etc.
You're treading on flammable ground here. I wouldn't want LASH to have the
slightest authority over what toolkits and/or widgets the clients are coded
with. And I don't see any reason why LASH should even care; LASH isn't a
plugin host. I should be able to include an Ncurses-based drum machine with
my session if I please.
Automatic client installation
This sounds an awful lot like stepping on the toes of packagers and
package managers. Unless you mean something completely different, of
course.
What's meant is: if you load a session and it includes a client that
isn't installed on the system, then make it such that it is installed
and the session can be loaded. This is no small thing. There are a few
options:
1. Create a system which abstracts package management for different
distros
2. Try and create an automatic compilation environment, similar to
ports on Freebsd or portage on Gentoo (lol)
3. Use autopackage
From the client side, this would be very simple: the programmer just
provides a URL to some meta-information that describes the packages
needed for that LASH client. I think this is pretty doable now that
number 3 exists.
Yes, you are stepping on packagers' toes here -- heavily.
Abstracting package management for distros is an insanely huge task, and not
likely to work in practice. Creating an automatic compilation environment --
well, I assume you're joking, because this would equal writing your own
source-based package manager. Using autopackage is out of the question,
because you simply can't fulfill the needs of all distros even with such a
system. (No, rpm and deb aren't the entire universe.)
If a session manager would take on package management like this -- which it
definitely _shouldn't_ in the first place -- it would have to work absolutely
_perfectly_ on _all_ possible distros. Either that, or nothing.
I'm a packager myself, for a smallish source-based distro called Source Mage.
The way our package manager works is likely to be incompatible with any other
system. I wouldn't want autopackage messing around with my box -- I want
packages installed the way they normally are with Source Mage.
Considering how you've been defending LASH from features that you deem outside
of its domain, I'm surprised that you would come up with this idea.
There is something I could think of, though. Maybe LASH clients could register
a homepage URL or equivalent piece of information which would help the user
to hunt down the missing program in case he/she needs to? That's about as far
as I'd go along that path.
And I would add to that now:
0.6
Redesign client/server communication
Certificate based security/encryption
Why would managing an audio session demand that the connections be
certified and encrypted? Unless you're thinking network-wise (i.e.
sessions that span several networked computers).
I'm thinking network-wise.
As I've said before, I don't believe it's a good idea to add this stuff to the
client protocol. Inter-host communication is a different thing.
Rework API
Genericify patch-system specifics
Provide more useful event system (callbacks, etc)
I think that an API overhaul would be welcome, and especially using
callbacks would be an improvement. But it's not first priority (thought
not the lowest either).
The API is pretty central, considering that both clients and the server
share most of it. It is that from which all else comes. Hence, IMHO,
pretty high priority.
I can understand your point. It may well be that fixing the API takes
precedence over much of the other changes.
Rewrite client library in gobject
Rewrite server in C++
These sent a cold shiver down my spine... mostly because I don't know C++
and I'm unwilling to learn it right now. :)
I've looked at the LASH code, and I must say it looks very well written.
You've done a great job. I don't see any reason why the current codebase
would need an overhaul. How do you feel that a rewrite in C++ would help
LASH as a project?
I appreciate the compliment, but with hindsight there are a lot of
things that could have been done much better. In general, the whole
thing would benefit greatly from object orientation.
Given this and the desire to present a C API, there are few options.
You could write the library and server both in C++ and provide a C
wrapper API/ABI. However, wrapping gobject APIs for C++ (and python,
and perl, and Java, and C#, etc, etc) has already been done a gazillion
times before. I know there are tools to help automate C++ wrapping
(which gtkmm et al use.) The weight is all leaning in gobject's
direction.
I'd use C++ for the server because a) C++ rocks, 2) the server doesn't
need to provide an external C ABI, and d) C++ rocks, and that's what I'd
want to use :-)
Yes, personal preference, we meet again. :)
And about
GObject... well, why bother? I understood from your reply to
Nedko that you're not suggesting that GObject be enforced into the actual
LASH API, which is a relief. I fail to see any benefit in GObject-ifying
the internals, either.
Object orientation. Events and configs in the communication system
share a lot of functionality. The patch system-specific functionality
could and should be generalised. In the server, the JACK- and
ALSA-specific functionality provide almost identical interfaces. When
writing it, I actually cut-and-pasted a lot of the function prototypes,
just changing "jack" to "alsa". A lot of the function bodies were
also
identical algorithms, only using the different JACK- and ALSA-specific
interfaces for the data. There's a lot of code in a lot of places that
could be made a lot better using objects.
Well, whoever writes the code gets to decide I guess.
Juuso