1111
1121
feeding a plugin having one audio input and two audio outputs,
1112
1122
the extra copy of the first plugin is redundant and not required,
1113
1123
but currently it is created anyway.
1116
\chapter{Internals -- how it works}
1117
This chapter explains how MusE is built internally, and is meant
1118
to be an aid for developers wanting to quickly start up with MusE.
1119
For details on \emph{why} stuff is done please refer to the following
1122
\section{User interface programming}
1123
We use the QT Toolkit for GUI- and other programming. The \emph{QT-Assistant}
1124
is an important tool for getting help. Almost everything can be looked
1127
GUIs can be either be hardcoded (see \file{arranger.cpp} for an example)
1128
or can be created using \emph{QT-Designer} (see the dialogs under
1129
\file{widgets/function_dialogs/} for mostly cleanly-written examples).
1130
Don't forget to add your \file{cpp}, \file{h} and \file{ui} files to the
1131
corresponding sections in the \file{CMakeLists.txt}!
1133
Additionally, MusE offers some custom widgets, like menu title items etc.
1134
Following, there will be a small, unordered list about custom widgets:
1136
\item \sym{MusEGui::MenuTitleItem}: Provides a title-bar in a \sym{QMenu}. \\
1137
Usage: \listing{someMenu->addAction(new MusEGui::MenuTitleItem(tr("fnord"), someMenu));} \\
1138
Defined in \file{widgets/menutitleitem.h}.
1139
\item \sym{MusEGui::PopupMenu}: Provides a \sym{QMenu}-like menu which
1140
can stay open after the user checks a checkable action.\\
1141
Usage: just create a \listing{new PopupMenu( true|false )} instead of
1142
a \listing{new QMenu()}. (\listing{true} means 'stay open')\\
1143
Defined in \file{widgets/popupmenu.h}.
1147
\section{Configuration} \label{portconfig_sucks}
1148
Configuration is a bit pesky in MusE in its current state. If you get
1149
confused by reading this chapter, that's a sign of a sane mind.
1151
There are three kinds of configuration items:
1153
\item (1) Global configuration, like coloring schemes, plugin categories, MDI-ness settings
1154
\item (2) Per-Song configuration, like whether to show or hide certain track types in the arranger
1155
\item (3) Something in between, like MIDI port settings etc. They obviously actually are
1156
global configuration issues (or ought to be), but also obviously must be stored
1157
in the song file for portability. (This problem could possibly be solved by
1158
the feature proposal in \ref{symbolic_ports}.
1161
\paragraph{Reading configuration}
1162
\sym{void MusECore::readConfiguration(Xml\&, bool, bool)} in
1163
\file{conf.cpp} is the central point
1164
of reading configuration. It is called when MusE is started first
1165
(by \sym{bool MusECore::readConfiguration()}), and also when a
1166
song is loaded. \\ %TODO: call paths!
1167
It can be instructed whether to read MIDI ports (3), global configuration
1168
and MIDI ports (1+3). Per-Song configuration is always read (2).
1170
When adding new configuration items and thus altering \sym{readConfiguration()},
1171
you must take care to place your item into the correct section. The code is
1172
divided into the following sections:
1174
\item Global and/or per-song configuration (3)
1175
\item Global configuration (1)
1176
\item Code for skipping obsolete entries
1179
The sections are divided by comments (they contain \texttt{----}, so just
1180
search for them). Please do not just remove code for reading obsolete entries,
1181
but always add an appropriate entry to the 'skipping' section in order to
1182
prevent error messages when reading old configs.
1184
\paragraph{Writing configuration}
1185
Global configuration is written using the
1186
\sym{MusEGui::MusE::writeGlobalConfiguration()} functions, while
1187
per-song-config is written by \sym{MusEGui::MusE::writeConfiguration()}
1188
(notice the missing \sym{Global}; both implemented in \file{conf.cpp}).
1190
\sym{writeConfiguration} is actually just a subset of the code in
1191
\sym{writeGlobalConfiguration}. \textbf{Duplicate code!} % TODO fix that in the sourcecode.
1193
\paragraph{Song state}
1194
Additionally to per-song configuration, there is the song's state.
1195
This contains "the song", that is all tracks, parts and note events,
1196
together with information about the currently opened windows, their
1197
position, size, settings and so on. Adding new items here is actually
1198
pretty painless: Configuration is read and written using
1199
\sym{MusECore::Song::read} and \sym{::write}, both implemented in
1200
\file{songfile.cpp}. There are no caveats.
1202
\paragraph{How to add new items}
1203
When adding global configuration items, then add them into the second
1204
block ("global configuration") in \sym{readConfiguration} and into
1205
\sym{writeGlobalConfiguration}.
1207
When adding just-per-song items, better don't bother to touch the
1208
"configuration" code and just add it to the song's state (there might
1209
be rare exceptions).
1211
When adding global configuration items, make sure you add them into the
1212
correct section of \sym{readConfiguration}, and into \sym{writeGlobalConfiguration}.
1215
%TODO: how to write config,
1216
%TODO: song/global stuff
1217
%TODO: config lesen und schreiben fuer plugingroups
1220
\section{User controls and automation}
1221
\subsection{Handling user input}
1222
\subsubsection{Plugins and synthesizers}
1223
\paragraph{Overview}
1224
When the user launches a plugin's GUI, either a MusE-window with
1225
the relevant controls is shown, or the native GUI is launched. MusE
1226
will communicate with this native GUI through OSC (Open Sound Control).
1227
The relevant classes are \sym{PluginGui}, \sym{PluginIBase}
1228
(in \file{plugin.h}) and \sym{OscIF} (in \sym{osc.h}).
1230
If the user changes a GUI element, first the corresponding control is
1231
disabled, making MusE not steadily update it through automation
1232
while the user operates it. Then MusE will update the plugin's parameter
1233
value, and also record the new value. When appropriate, the controller
1236
\paragraph{Processing the input, recording}
1237
Upon operating a slider, \sym{PluginIBase::setParam} is called,
1238
which usually writes the control change into the ringbuffer
1239
\sym{PluginI::{\_}controlFifo}. (\sym{PluginI::apply()},
1240
\sym{DssiSynthIF::getData()} will read this ringbuffer and
1241
do the processing accordingly). Furthermore, \sym{AudioTrack::recordAutomation}
1242
is called, which either directly modifies the controller lists or writes
1243
the change into a "to be recorded"-list (\sym{AudioTrack::{\_}recEvents})
1244
(depending on whether the song is stopped or played).
1246
The \sym{AudioTrack::{\_}recEvents} list consists of \sym{CtrlRecVal}
1247
items (see \file{ctrl.h}), which hold the following data:
1249
\item the frame where the change occurred
1251
\item the type, which can be \usym{ARVT{\_}START}, \usym{ARVT{\_}VAL} or \usym{ARVT{\_}STOP}.
1252
\usym{ARVT{\_}VAL} are written by every \usym{AudioTrack::recordAutomation}
1253
call, \usym{ARVT{\_}START} and \usym{ARVT{\_}STOP} are generated by
1254
\sym{AudioTrack::startAutoRecord} and \sym{stopAutoRecord}, respectively.
1255
\item and the id of the controller which is affected
1257
It is processed when the song is stopped. The call path for this is:
1258
\sym{Song::stopRolling} calls \sym{Song::processAutomationEvents}
1259
calls \sym{AudioTrack::processAutomationEvents}.
1260
This function removes the old events from the track's controller list
1261
and replaces them with the new events from \sym{{\_}recEvents}. In
1262
\usym{AUTO{\_}WRITE} mode, just all controller events within the recorded
1263
range are erased; in \usym{AUTO{\_}TOUCH} mode, the \usym{ARVT{\_}START}
1264
and \usym{ARVT{\_}STOP} types of the \sym{CtrlRecVal} events are used
1265
to determine the range(s) which should be wiped.
1267
\paragraph{How it's stored}
1268
Automation data is kept % this is copied from
1269
in \sym{AudioTrack::{\_}controller}, which is a \sym{CtrlListList}, % "design decisions" -> "automation"
1270
that is, a list of \sym{CtrlList}s, that is, a list of lists of
1271
controller-objects which hold the control points of the automation graph.
1272
The \sym{CtrlList} also stores whether the list is meant discrete
1273
(a new control point results in a value-jump) or continuous (a new control
1274
point results in the value slowly sloping to the new value).
1275
Furthermore, it stores a \sym{{\_}curVal} (accessed by \sym{curVal()}),
1276
which holds the currently active value, which can be different from the
1277
actually stored value because of user interaction. This value is also
1278
used when there is no stored automation data.
1280
\sym{AudioTrack::addController} and \sym{removeController} are used % TODO: swapControllerIDX??
1281
to add/remove whole controller types; the most important functions which
1282
access \sym{{\_}controller} are:
1284
\item \sym{processAutomationEvents}, \sym{recordAutomation},
1285
\sym{startAutoRecord}, \sym{stopAutoRecord}: see above.
1286
\item \sym{seekPrevACEvent}, \sym{seekNextACEvent}, \sym{eraseACEvent},
1287
\sym{eraseRangeACEvents}, \sym{addACEvent}, \sym{changeACEvent},
1288
which do the obvious
1289
\item \sym{pluginCtrlVal}, \sym{setPluginCtrlVal}: the first
1290
returns the current value according to the \sym{{\_}controller}
1291
list, the second only sets the \sym{curVal}, but does not
1295
Whenever a \sym{CtrlList} has been manipulated,
1296
\sym{MusEGlobal::song->controllerChange(Track{*})} shall be called,
1297
which emits the \sym{MusEGlobal::song->controllerChanged(Track{*})}
1298
signal in order to inform any parts of MusE about the change (currently,
1299
only the arranger's part canvas utilizes this).
1301
\paragraph{Enabling and disabling controllers}
1302
Disabling the controller is both dependent from the current automation
1303
mode and from whether the GUI is native or not.
1304
In \usym{AUTO{\_}WRITE} mode, once a slider is touched (for MusE-GUIs) or
1305
once a OSC control change is received (for native GUIs), the control
1306
is disabled until the song is stopped or seeked.
1308
In \usym{AUTO{\_}TOUCH} (and currently (r1492) \usym{AUTO{\_}READ}, but
1309
that's to be fixed) mode, once a MusE-GUI's slider is pressed down, the
1310
corresponding control is disabled. Once the slider is released, the
1311
control is re-enabled again. Checkboxes remain in "disabled" mode,
1312
however they only affect the recorded automation until the last toggle
1313
of the checkbox. (Example: start the song, toggle the checkbox, toggle
1314
it again, wait 10 seconds, stop the song. This will NOT overwrite the
1315
last 10 seconds of automation data, but everything between the first
1316
and the last toggle.). For native GUIs, this is a bit tricky, because
1317
we don't have direct access to the GUI widgets. That is, we have no
1318
way to find out whether the user doesn't touch a control at all, or
1319
whether he has it held down, but just doesn't operate it. The current
1320
behaviour for native GUIs is to behave like in \usym{AUTO{\_}WRITE} mode.
1322
The responsible functions are: \sym{PluginI::oscControl} and
1323
\sym{DssiSynthIF::oscControl} for handling native GUIs,
1324
\sym{PluginI::ctrlPressed} and \sym{ctrlReleased} for MusE
1325
default GUIs and \sym{PluginI::guiParamPressed},
1326
\sym{guiParamReleased}, \sym{guiSliderPressed} and
1327
\sym{guiSliderReleased} for MusE GUIs read from a UI file;
1328
\sym{guiSlider{*}} obviously handle sliders, while \sym{guiParam{*}}
1329
handle everything else which is not a slider. They call
1330
\sym{PluginI::enableController} to enable/disable it.
1332
Furthermore, on every song stop or seek, \sym{PluginI::enableAllControllers}
1333
is called, which re-enables all controllers again. The call paths for
1336
\item For stop: \sym{Song::stopRolling} calls
1337
\sym{Song::processAutomationEvents} calls
1338
\sym{Song::clearRecAu{\-}to{\-}ma{\-}tion} calls
1339
\sym{Track::clearRecAutomation} calls
1340
\sym{PluginI::enableAllControllers}
1341
\item For seek: \sym{Audio::seek} sends a message ("\sym{G}") to
1342
\sym{Song::seqSignal} which calls
1343
\sym{Song::clearRecAutomation} which calls
1344
\sym{PluginI::enableAllControllers}
1350
\chapter{Design decisions}
1351
\section{Automation}
1352
As of revision 1490, automation is handled in two ways: User-generated
1353
(live) automation data (generated by the user moving sliders while playing)
1354
is fed into \sym{PluginI::{\_}controlFifo}. Automation data is kept
1355
in \sym{AudioTrack::{\_}controller}, which is a \sym{CtrlListList},
1356
that is, a list of \sym{CtrlList}s, that is, a list of lists of
1357
controller-objects which hold the control points of the automation graph.
1358
The \sym{CtrlList} also stores whether the list is meant discrete
1359
(a new control point results in a value-jump) or continous (a new control
1360
point results in the value slowly sloping to the new value).
1362
While \sym{PluginI::{\_}controlFifo} can be queried very quickly and
1363
thus is processed with a very high resolution (only limited by the
1364
minimum control period setting), the automation value are expensive to
1365
query, and are only processed once in an audio \emph{driver} period.
1366
This might lead to noticeable jumps in value.
1368
This could possibly be solved in two ways:
1369
\paragraph{Maintaining a slave control list}
1370
This approach would maintain a fully redundant slave control list,
1371
similar to \sym{PluginI::{\_}controlFifo}. This list must be updated
1372
every time any automation-related thing is changed, and shall contain
1373
every controller change as a tuple of controller number and value.
1374
This could be processed in the same loop as \sym{PluginI::{\_}controlFifo},
1375
making it comfortable to implement; furthermore, it allows to cleanly
1376
offer automation-settings at other places in future (such as storing
1377
automation data in parts or similar).
1379
\paragraph{Holding iterators}
1380
We also could hold a list of iterators of the single \sym{CtrlList}s.
1381
This would also cause low CPU usage, because usually, the iterators only
1382
need to be incremented once. However, it is pretty complex to implement,
1383
because the iterators may become totally wrong (because of a seek in the
1384
song), and we must iterate through a whole list of iterators.
1386
\paragraph{Just use the current data access functions}
1387
By just using the current functions for accessing automation data,
1388
we might get a quick-and-dirty solution, which however wastes way too
1389
much CPU ressources. This is because on \emph{every single frame}, we
1390
need to do a binary search on multiple controller lists.
1393
\chapter{Feature requests}
1394
\section{Per-Part automation and more on automation} % by flo
1395
Automation shall be undo-able. Automation shall reside in parts which
1396
are exchangeable, clonable etc (like the MIDI- and Wave-Parts).
1397
Global per-synth/per-audiotrack automation shall also be available, but
1398
this can also be implemented as special case of part automation (one
1401
\section{Pre-Rendering tracks}
1402
\subsection{The feature}
1403
All tracks shall be able to be "pre-renderable". Pre-rendering shall
1404
be "layered". Pre-rendering shall act like a transparent audio cache:
1405
Audio data is (redundantly) stored, wasting memory in order to save CPU.
1407
That is: Each track owns one or more wave-recordings of the length of
1408
the song. If the user calls "pre-render" on a track, then this track
1409
is played quasi-solo (see below), and the raw audio data is recorded
1410
and stored in the "layer 0" wave recording. If the user has any effects
1411
set up to be applied, then each effect is applied on a different layer
1412
(creating layer 1, layer 2 etc).
1414
This means, that also MIDI and drum tracks can have effects (which
1415
usually only operate on audio, but we HAVE audio data because of this
1418
Furthermore, MusE by default does not send MIDI events to the synthesizers
1419
but instead just plays back the last layer of the prerecording (for
1420
MIDI tracks), or does not pipe the audio data through the whole plugin
1421
chain (causing cpu usage), but instead just plays back the last layer.
1422
The hearable result shall be the same.
1424
Once the user changes any parameter (automation data or plugins for
1425
wave tracks, MIDI events or effect plugin stuff for MIDI tracks),
1426
then MusE shall generate the sound for this particular track in the
1427
"old" way (send MIDI data to synthes, or pipe audio data through plugins).
1428
(So that the user will not even notice that MusE actually pre-renderered
1429
stuff.) Either MusE automatically records this while playback (if possible)
1430
or prompts the user to accordingly set up his cabling and then record
1431
it. Or (temporarily) disables prerecording for this track, falling back
1432
to the plain old way of generating sound.
1434
\emph{Quasi-solo} means: For wave tracks, just solo the track. For MIDI
1435
tracks, mute all tracks which are not on the same synth (channel?),
1436
and mute all \emph{note} events which are not on the quasi-soloed track.
1437
This causes MusE to still play any controller events from different
1438
tracks, because they might have effects on the quasi-soloed track. (You
1439
can have notes on channel 1 on one track and controller stuff on channel
1440
1 on another track; then you would need quasi-solo to get proper results.)
1442
\subsection{Use cases}
1443
\paragraph{Saving CPU}
1444
On slow systems, this is neccessary for songs with lots of, or demanding
1445
(or both) soft synthes / plugins. Even if the synth or plugin is so
1446
demanding that your system is not able to produce sound in real-time,
1447
then with this feature you'll be able to use the synth (this will make
1448
editing pretty laggish, because for a change you need to re-render at
1449
least a part before you can listen to it, but better than being unable
1450
to use the synth at all!)
1452
\paragraph{Exporting as audio project}
1453
Using pre-rendering on all tracks, you easily can export your project
1454
as multi-track audio file (for use with Ardour or similar DAWs).
1455
Just take the last layer of each track, and write the raw audio data
1456
into the file, and you're done. (Maybe we are even able to write down
1457
the raw-raw layer0 audio data plus information about used plugins and
1460
\paragraph{Mobile audio workstations}
1461
You might want to work a bit on your audio projects on your notebook
1462
while you're not at home, not having access to your hardware synthesizers.
1463
Using this feature, you could have pre-recorded the stuff in your studio
1464
before, and now can at least fiddle around with the non-hw-synth-dependent
1465
parts of your song, while still having your \emph{full} song with you.
1467
\paragraph{Applying effects on MIDI tracks}
1468
If you have many physical audio inputs, you might already be able to
1469
apply effect chains on MIDI tracks, by wiring the synthes' audio
1470
outputs to your soundcard's inputs, and applying the effects on
1471
dedicated input tracks you have to create. This requires you to have
1472
expensive hardware, and is pretty complicated, because you need one
1473
additional track per MIDI synth.
1475
This feature allows you to apply effects on single MIDI tracks, and not
1476
only on full MIDI synthes, and doesn't require you to be have that
1477
many physical audio inputs (you need to manually replug your synthes,
1480
\subsection{Possible scenarios}
1481
\paragraph{Setting it up}
1482
Create a wave track, MusE will allow you to set or unset prerendering
1483
for every plugin in the plugin rack (recording the actual track is
1484
useless because it would be a plain copy).
1485
Create a MIDI track, MusE will ask you on which physical audio input
1486
your synth is connected. Setting up multiple synthes on one physical
1487
audio in is allowed, see below.
1489
\paragraph{Pre-rendering stuff}
1490
When the user presses the "pre-render" button, all tracks which have
1491
been changed since their last pre-rendering will be re-rendered.
1492
If you have multiple hardware synthes set up as they were connected
1493
to one physical audio input port, MusE will prompt you to first plug
1494
the proper cable in.
1496
\paragraph{Making changes}
1497
Change a note in a MIDI part, move or delete a part or change automation
1498
parameters. MusE will temporarily disable the pre-rendered information
1499
and instead generate the sound via sending out MIDI events, piping stuff
1500
through effect chains or similar. If you play back the whole song, or
1501
if you manually trigger a re-rendering of a track via the context menu,
1502
MusE will play back the stuff, record it again and re-enable the
1503
pre-rendered information.
1506
\subsection{Extensions}
1507
\paragraph{Automatic discovery of physical audio connections}
1508
The user plugs all (or only some) synthes' audio outs into the available
1509
audio inputs, then runs automatic discovery. This will send MIDI events
1510
to each synthesizer, and look on which audio in there's activity. Then
1511
it will assume that the synthesizer is connected to that particular
1512
audio in. Audio ins which show activity before any MIDI events were
1513
sent are not considered, as they're probably connected to microphones
1514
or other noise-generating non-synthes.
1516
\paragraph{Audio export}
1517
As described in the Use cases, MusE can allow you to export your song
1518
in some multitrack audio format.
1520
\paragraph{Cheap/Faked changes}
1521
For expensive or unavailable synthes, changing the Volume midi controller,
1522
the Pan controller or similar "easy" controllers will not trigger a
1523
complete re-rendering, but instead "fake" the change, by changing
1524
the volume data directly on the recorded wave. This might require some
1525
learning and might even get pretty complicated.
1527
\paragraph{Intelligent re-recording}
1528
For tiny changes, MusE shall only re-render the relevant part. If you
1529
change some MIDI notes, then begin re-recording shortly before the
1530
changes, and end re-recording as soon as the recorded stuff doesn't
1531
differ to much from the stuff coming from the synth. Then properly
1532
blend the old recording with the updated part.
1536
\section{Slotted editors}
1537
Currently, MusE has the pianoroll editor, drum editor, score editor,
1538
then the controller editor which is inside the pianoroll/drum editor.
1539
All these editors have a very similar concept: the "time axis" is
1540
vertical and (almost) linear, they handle parts, and events are
1541
manipulated similarly.
1543
A unified editor shall be created which allows you to combine different
1544
kinds of editors in one window, properly aligned against each other.
1545
These "different kinds of editors" shall be handled as "slots"; one
1546
unified editor window consists of:
1548
\item A menu bar, containing stuff suitable for the complete window,
1549
which might include window name, MDI-ness etc.
1550
\item A toolbar which contains controls suitable for every single slot.
1551
\item A container with one or more slots; the slots can be scrolled in
1552
y-direction if there are multipe slots.
1553
\item A time-scrollbar with zoom
1556
Each slot contains the following:
1558
\item A menu button, button box or control panel for setting up this
1559
particular slot. This could contain "note head colors", "show
1560
a transposing instrument" etc for score edit slots, "event
1561
rectangle color", "grid size" and "snap to grid" for pianoroll/
1563
\item The actual canvas
1564
\item A y-direction scroll bar, possibly with zoom control (for
1568
The main window does not show its scroll bar if there is only one slot,
1569
because the slot's scrollbar is sufficient then.
1571
Slots can be added, destroyed, moved around, maybe even merged (if the
1572
slot types allow it); basically, you can compare them with the staves
1573
in the score editor.
1575
The slots shall align against each other, that is, if a score editor
1576
slot displays a key change with lots of accidentials, then all other
1577
slots shall either also display the key change (if they're score slots)
1578
or display a gap. Events which happen at the same time shall be at the
1579
same x-coordinate, regardless which slot they are.
1581
\section{Controller master values}
1582
All controllers (MIDI-controllers and also automation controllers)
1583
shall have one set of "master values" which allow you to set a gain and
1584
a bias. Instead of the actual set value, $\textrm{value} * \textrm{bias}
1585
+ textrm{bias}$ shall be sent to the MIDI device / the plugin. For
1586
controllers like "pan", the unbiased values shall be transformed, that
1587
is, a pan of 64, with $\textrm{bias}=2$ and $\textrm{gain}=0.5$, shall
1588
be transformed to 66 (because 64 is actually 0, while 0 is actually -64).
1589
These values shall be set in the arranger and whereever the actual
1590
controller/automation values can be edited.
1592
\section{Enabled-indicator while recording}
1593
The MusE-plugin-GUIs shall display a small LED displaying whether a
1594
controller is currently enabled or disabled. By clicking this LED, the
1595
enabled state shall be switched.
1597
Furthermore, there shall be a dedicated window which only lets you switch
1598
enabled/disabled states. This will be useful when using external GUIs
1599
or the MIDI-controller-to-automation feature, to re-enable a controller
1600
when in \usym{AUTO{\_}TOUCH} mode.
1604
\section{Linear automation editing}
1605
While holding some modifier key (like shift), operating the MusE-native-
1606
GUI sliders shall only generate control points when clicking and when
1607
releasing the slider. This will result in linear graphs for continous
1608
controllers, and in large steps for discrete controllers (which is in
1609
particular useful for stuff like "which low/high-pass filter type to use").
1611
Maybe make this behaviour default for discrete controllers?
1613
\section{Symbolic names for MIDI ports} \label{symbolic_ports}
1614
MIDI ports shall have a user-defined symbolic name (like "Korg" or "Yamaha DX 7").
1615
The mapping between these symbolic names and the hardware port (like
1616
"ALSA midi out port") is stored in the global configuration.
1618
Song files only specify the symbolic names as the ports associated with
1619
their tracks. No information about physical devices/port names, but only
1620
symbolic names are stored in the song file.
1622
This resolves the issues mentioned in \ref{portconfig_sucks}, and also
1623
allows the user to share his pieces with other people: They would only
1624
have to set up that symbolic-to-hardware mapping once (collisions are
1625
unlikely, because an equal symbolic name should usually mean the same
1626
device) and are happy, instead of having to re-map \emph{every} port
1627
for \emph{every} song.
1631
% TODO: song type etc? kill it!
1632
% song len box: same
1634
% TODO: unified automation and midi ctrls:
1635
% both shall be editable through the same editors
1636
% four modes: 1. discrete
1637
% 2. continous (plus a global and per-port setting for the max rate)
1638
% 3. switch (not necessarily ON/OFF; signals with color plus text annotation)
1639
% 4. raw (no graph, instead a box with the value sent out (for "all voices off")
1640
% they shall be copy-and-pastable, at least between compatible modes
1641
% they shall be slotted, like pianoroll
1642
% maybe also "overlapping", like arranger (?)
1643
% midi recording tries to make out straight lines (like non-ended automation streams)
1647
% new song (in general: load as template) plus "overwrite port config"
1648
% should re-create the default jack devices and autoconnect them.
1650
% what's audio aux for?
1652
% bug in arranger/pcanvas/automation: if a controlpoint is directly on
1653
% a line of another ctrl graph, you can't click it