summaryrefslogtreecommitdiff
path: root/muse2/doc/developer_docs.tex
diff options
context:
space:
mode:
authorTim E. Real <termtech@rogers.com>2013-02-22 06:46:23 +0000
committerTim E. Real <termtech@rogers.com>2013-02-22 06:46:23 +0000
commit48b9d2ea9961f935bacabc75a2fbd5cc141010ae (patch)
tree37512a1feed9d02145e0e52f0c96e5fe42a83f62 /muse2/doc/developer_docs.tex
parent2d1fc0416a2d8611659a4f630fbc5719f35b694d (diff)
New: Install pre-built PDF + single/split HMTL docs. Separate devel docs. Added build script.
Diffstat (limited to 'muse2/doc/developer_docs.tex')
-rw-r--r--muse2/doc/developer_docs.tex702
1 files changed, 702 insertions, 0 deletions
diff --git a/muse2/doc/developer_docs.tex b/muse2/doc/developer_docs.tex
new file mode 100644
index 00000000..bc3cdc86
--- /dev/null
+++ b/muse2/doc/developer_docs.tex
@@ -0,0 +1,702 @@
+%% (c) 2012 florian jung
+%% (c) 2012 Robert Jonsson
+%% we should consider putting this under a proper license. GPL, or
+%% some GPL-like documentation license??
+
+%% rules for editing documentation: (READ THIS FIRST)
+%% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+%%
+%% please try to let newly written lines be shorter than 72 characters.
+%% minor exceptions are okay, but please not more than 80 chars.
+%% comments shall start after character #80 of the line (that is,
+%% they shall be "on the right margin")
+%%
+%% DON'T MIX up changes and reformatting in one commit. when changing
+%% stuff, please don't touch the lines before and after your change
+%% (that is, do not re-wrap them), even if it will look a bit patchy.
+%% this is for being able to easily use diff.
+%% when you want to reformat this file, then do it. but don't change
+%% anything, as this would be hard to find in a diff. and clearly
+%% state in the commit log that you "only" rearranged things.
+%%
+%% please adhere to the "User's manual" / "Internals" / "Design"
+%% partitioning (genereally, don't change the chapters until there
+%% is a really good reason for doing so (adding a chapter like
+%% "feature requests" as flo did in r1497 IS one).
+%% Below that, feel free to change the logical arrangement
+%% (making paragraphs to subsections and similar) if you deem it
+%% neccessary.
+%%
+%% Whenever referring to code symbols, constants or source/header
+%% files, please use \sym{someClass::someSymbol}, \usym{UPPERCASE_THING}
+%% or \f{file.cpp}.
+%% Only specify file paths or namespaces where it would be ambiguous
+%% otherwise. Specify 'someClass::' until it would disturb the reader
+%% and it is obvious. you have to replace '_' by {\_} (with the {}!).
+%% These macros do automatic hyphenation on Camel-Case, under_-score
+%% and scope::-operator boundaries. If you need to insert additional
+%% hyphenation points, use {\-}.
+%% Example: \sym{someClass::someAb{\-}nor{\-}mal{\-}lyLongName} will
+%% hyphenate: some-Class::-some-Ab-nor-mal-ly-Long-Name
+%%
+%% Whenever referring to URLs, please wrap them in \url{blah}. Key
+%% combinations shall look like \key{CTRL+C}. Menu items shall look
+%% like \menu{Menu > Submenu > Menu Item}.
+%%
+%% Where possible, reference other parts of this documents with
+%% \label and \ref. Avoid duplicate information under "Internals" by
+%% referring to the appropriate section in "User's manual".
+%%
+%% Please do no time-stamping of sections. if you need time-stamps,
+%% use "svn blame documentation.tex"
+%%
+%% If you contribute something, feel free to add yourself to \author.
+%%
+%% If you don't speak LaTeX fluently, a few tips:
+%% * \section, \subsection, \subsubsection, \paragraph, \subparagraph
+%% let you create sections etc. just copy-and-paste if unsure.
+%% * you must prefix special characters like the underscore with \
+%% (backslash)
+%% * \emph{some text} emphasizes the text, printing it italic.
+%% * \texttt{some text} displays the text in a typewriter font
+%% * \label{someName} creates a label at this position. this doesn't
+%% show up in the pdf. with \ref{someName}, you can reference to this
+%% label. (LaTeX will insert the section number instead of \ref)
+%% For this to work, you might need to recompile the .tex twice.
+%%
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Dependencies:
+%% To produce pdf output from this document the following packages are
+%% needed (atleast under Ubuntu derivatives)
+%% latex???-base
+%% texlive-latex-recommended
+%% texlive-latex-extra
+%%
+%% To produce a pdf version of this manual type:
+%% pdflatex documentation.tex <enter>
+%% A file documentation.pdf should be generated.
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+\documentclass[a4paper]{report}
+\usepackage[a4paper, left=2.5cm, right=2.5cm, top=2.5cm, bottom=2.5cm]{geometry}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{lmodern}
+\usepackage[english]{babel}
+\usepackage{graphicx}
+\usepackage{hyphenat}
+\usepackage{wrapfig}
+\usepackage{fancyhdr}
+\usepackage{hyperref}
+\usepackage{xcolor}
+\hypersetup{
+ linkcolor=blue,
+ urlcolor=blue,
+ colorlinks=true, % hyperlinks will be blue
+ linkbordercolor=blue, % hyperlink borders will be blue
+ %pdfborderstyle={/S/U/W 1} % border style will be underline of width 1pt
+}
+\pagestyle{fancy}
+ \lhead{\scriptsize{\slshape\leftmark}}
+ \chead{}
+ \rhead{\thepage}
+ \lfoot{}
+ \cfoot{}
+ \rfoot{}
+ \renewcommand{\headrulewidth}{0.4pt}
+\usepackage{ifthen}
+
+%% Borrowed from Lyx output. "Because html converters don't know
+%% tabularnewline". Is required? Maybe replace with \\ ?
+\providecommand{\tabularnewline}{\\}
+
+% Hyphenate symbols before each uppercase letter, after each underscore
+% (without a "-") and after each ':' (without a "-")
+% TODO for any latex crack: also do automatic hyphenation, that is,
+% instead of some-Automation-Expression, do some-Au-to-ma-tion-Ex-press-ion
+\makeatletter
+\newcommand{\camelhyph}[1]{\@fterfirst\c@amelhyph#1\relax }
+\newcommand{\underscorehyph}[1]{\@fterfirst\u@nderscorehyph#1\relax }
+\def\@fterfirst #1#2{#2#1}
+\def\c@amelhyph #1{%
+\ifthenelse{\equal{#1}\relax}{}{% Do nothing if the end has been reached
+ \ifnum`#1=95 \_\hspace{0pt}\else % Check whether #1 is "_", then print _[thin space]
+ \ifnum`#1=58 :\hspace{0pt}\else
+ \ifnum`#1>64
+ \ifnum`#1<91 \-#1\else#1\fi% Check whether #1 is an uppercase letter,
+ \else#1\fi
+ \fi
+ \fi
+ % if so, print \-#1, otherwise #1
+ \expandafter\c@amelhyph% % insert \c@amelhyph again.
+}}
+\def\u@nderscorehyph #1{%
+\ifthenelse{\equal{#1}\relax}{}{% Do nothing if the end has been reached
+ \ifnum`#1=95 \_\hspace{0pt}\else % Check whether #1 is "_", then print _\-
+ \ifnum`#1=58 :\hspace{0pt}\else#1\fi\fi
+ \expandafter\u@nderscorehyph% % insert \u@nderscorehyph again.
+}}
+\makeatother
+
+
+
+\author{Florian Jung, Robert Jonsson, Tim Donnelly}
+\title{MusE Documentation}
+
+% Orcan: not needed since the hyperref package takes care of all
+%\newcommand{\url}[1]{\texttt{#1}}
+\newcommand{\key}[1]{\textbf{#1}}
+\newcommand{\shell}[1]{\texttt{\textbf{#1}}}
+\newcommand{\menu}[1]{\textbf{#1}}
+\newcommand{\sym}[1]{\texttt{\camelhyph{#1}}}
+\newcommand{\listing}[1]{\texttt{\camelhyph{#1}}}
+\newcommand{\usym}[1]{\texttt{\underscorehyph{#1}}}
+\newcommand{\file}[1]{\texttt{\camelhyph{#1}}}
+\newcommand{\screenshotwidth}[0]{0.8\textwidth}
+
+\begin{document}
+\tableofcontents
+\chapter{Internals -- how it works}
+This chapter explains how MusE is built internally, and is meant
+to be an aid for developers wanting to quickly start up with MusE.
+For details on \emph{why} stuff is done please refer to the following
+chapter.
+
+\section{User interface programming}
+We use the QT Toolkit for GUI- and other programming. The \emph{QT-Assistant}
+is an important tool for getting help. Almost everything can be looked
+up there.
+
+GUIs can be either be hardcoded (see \file{arranger.cpp} for an example)
+or can be created using \emph{QT-Designer} (see the dialogs under
+\file{widgets/function_dialogs/} for mostly cleanly-written examples).
+Don't forget to add your \file{cpp}, \file{h} and \file{ui} files to the
+corresponding sections in the \file{CMakeLists.txt}!
+
+Additionally, MusE offers some custom widgets, like menu title items etc.
+Following, there will be a small, unordered list about custom widgets:
+\begin{itemize}
+\item \sym{MusEGui::MenuTitleItem}: Provides a title-bar in a \sym{QMenu}. \\
+ Usage: \listing{someMenu->addAction(new\ MusEGui::MenuTitleItem(tr("fnord"),\ someMenu));} \\
+ Defined in \file{widgets/menutitleitem.h}.
+\item \sym{MusEGui::PopupMenu}: Provides a \sym{QMenu}-like menu which
+ can stay open after the user checks a checkable action.\\
+ Usage: just create a \listing{new\ PopupMenu(\ true|false\ )} instead of
+ a \listing{new\ QMenu()}. (\listing{true} means 'stay open')\\
+ Defined in \file{widgets/popupmenu.h}.
+\end{itemize}
+
+
+\section{Configuration} \label{portconfig_sucks}
+Configuration is a bit pesky in MusE in its current state. If you get
+confused by reading this chapter, that's a sign of a sane mind.
+
+There are three kinds of configuration items:
+\begin{itemize}
+\item (1) Global configuration, like coloring schemes, plugin categories, MDI-ness settings
+\item (2) Per-Song configuration, like whether to show or hide certain track types in the arranger
+\item (3) Something in between, like MIDI port settings etc. They obviously actually are
+ global configuration issues (or ought to be), but also obviously must be stored
+ in the song file for portability. (This problem could possibly be solved by
+ the feature proposal in \ref{symbolic_ports}.
+\end{itemize}
+
+\paragraph{Reading configuration}
+\sym{void\ MusECore::readConfiguration(Xml\&,\ bool,\ bool)} in
+\file{conf.cpp} is the central point
+of reading configuration. It is called when MusE is started first
+(by \sym{bool\ MusECore::readConfiguration()}), and also when a
+song is loaded. \\ %TODO: call paths!
+It can be instructed whether to read MIDI ports (3), global configuration
+and MIDI ports (1+3). Per-Song configuration is always read (2).
+
+When adding new configuration items and thus altering \sym{readConfiguration()},
+you must take care to place your item into the correct section. The code is
+divided into the following sections:
+\begin{itemize}
+\item Global and/or per-song configuration (3)
+\item Global configuration (1)
+\item Code for skipping obsolete entries
+\end{itemize}
+
+The sections are divided by comments (they contain \texttt{----}, so just
+search for them). Please do not just remove code for reading obsolete entries,
+but always add an appropriate entry to the 'skipping' section in order to
+prevent error messages when reading old configs.
+
+\paragraph{Writing configuration}
+Global configuration is written using the
+\sym{MusEGui::MusE::writeGlobalConfiguration()} functions, while
+per-song-config is written by \sym{MusEGui::MusE::writeConfiguration()}
+(notice the missing \sym{Global}; both implemented in \file{conf.cpp}).
+
+\sym{writeConfiguration} is actually just a subset of the code in
+\sym{writeGlobalConfiguration}. \textbf{Duplicate code!} % TODO fix that in the sourcecode.
+
+\paragraph{Song state}
+Additionally to per-song configuration, there is the song's state.
+This contains "the song", that is all tracks, parts and note events,
+together with information about the currently opened windows, their
+position, size, settings and so on. Adding new items here is actually
+pretty painless: Configuration is read and written using
+\sym{MusECore::Song::read} and \sym{::write}, both implemented in
+\file{songfile.cpp}. There are no caveats.
+
+\paragraph{How to add new items}
+When adding global configuration items, then add them into the second
+block ("global configuration") in \sym{readConfiguration} and into
+\sym{writeGlobalConfiguration}.
+
+When adding just-per-song items, better don't bother to touch the
+"configuration" code and just add it to the song's state (there might
+be rare exceptions).
+
+When adding global configuration items, make sure you add them into the
+correct section of \sym{readConfiguration}, and into \sym{writeGlobalConfiguration}.
+
+
+%TODO: how to write config,
+%TODO: song/global stuff
+%TODO: config lesen und schreiben fuer plugingroups
+
+
+\section{User controls and automation}
+\subsection{Handling user input}
+\subsubsection{Plugins and synthesizers}
+\paragraph{Overview}
+When the user launches a plugin's GUI, either a MusE-window with
+the relevant controls is shown, or the native GUI is launched. MusE
+will communicate with this native GUI through OSC (Open Sound Control).
+The relevant classes are \sym{PluginGui}, \sym{PluginIBase}
+(in \file{plugin.h}) and \sym{OscIF} (in \sym{osc.h}).
+
+If the user changes a GUI element, first the corresponding control is
+disabled, making MusE not steadily update it through automation
+while the user operates it. Then MusE will update the plugin's parameter
+value, and also record the new value. When appropriate, the controller
+is enabled again.
+
+\paragraph{Processing the input, recording}
+Upon operating a slider, \sym{PluginIBase::setParam} is called,
+which usually writes the control change into the ringbuffer
+\sym{PluginI::{\_}controlFifo}. (\sym{PluginI::apply()},
+\sym{DssiSynthIF::getData()} will read this ringbuffer and
+do the processing accordingly). Furthermore, \sym{AudioTrack::recordAutomation}
+is called, which either directly modifies the controller lists or writes
+the change into a "to be recorded"-list (\sym{AudioTrack::{\_}recEvents})
+(depending on whether the song is stopped or played).
+
+The \sym{AudioTrack::{\_}recEvents} list consists of \sym{CtrlRecVal}
+items (see \file{ctrl.h}), which hold the following data:
+\begin{itemize}
+\item the frame where the change occurred
+\item the value
+\item the type, which can be \usym{ARVT{\_}START}, \usym{ARVT{\_}VAL} or \usym{ARVT{\_}STOP}.
+ \usym{ARVT{\_}VAL} are written by every \usym{AudioTrack::recordAutomation}
+ call, \usym{ARVT{\_}START} and \usym{ARVT{\_}STOP} are generated by
+ \sym{AudioTrack::startAutoRecord} and \sym{stopAutoRecord}, respectively.
+\item and the id of the controller which is affected
+\end{itemize}
+It is processed when the song is stopped. The call path for this is:
+\sym{Song::stopRolling} calls \sym{Song::processAutomationEvents}
+calls \sym{AudioTrack::processAutomationEvents}.
+This function removes the old events from the track's controller list
+and replaces them with the new events from \sym{{\_}recEvents}. In
+\usym{AUTO{\_}WRITE} mode, just all controller events within the recorded
+range are erased; in \usym{AUTO{\_}TOUCH} mode, the \usym{ARVT{\_}START}
+and \usym{ARVT{\_}STOP} types of the \sym{CtrlRecVal} events are used
+to determine the range(s) which should be wiped.
+
+\paragraph{How it's stored}
+Automation data is kept % this is copied from
+in \sym{AudioTrack::{\_}controller}, which is a \sym{CtrlListList}, % "design decisions" -> "automation"
+that is, a list of \sym{CtrlList}s, that is, a list of lists of
+controller-objects which hold the control points of the automation graph.
+The \sym{CtrlList} also stores whether the list is meant discrete
+(a new control point results in a value-jump) or continuous (a new control
+point results in the value slowly sloping to the new value).
+Furthermore, it stores a \sym{{\_}curVal} (accessed by \sym{curVal()}),
+which holds the currently active value, which can be different from the
+actually stored value because of user interaction. This value is also
+used when there is no stored automation data.
+
+\sym{AudioTrack::addController} and \sym{removeController} are used % TODO: swapControllerIDX??
+to add/remove whole controller types; the most important functions which
+access \sym{{\_}controller} are:
+\begin{itemize}
+\item \sym{processAutomationEvents}, \sym{recordAutomation},
+ \sym{startAutoRecord}, \sym{stopAutoRecord}: see above.
+\item \sym{seekPrevACEvent}, \sym{seekNextACEvent}, \sym{eraseACEvent},
+ \sym{eraseRangeACEvents}, \sym{addACEvent}, \sym{changeACEvent},
+ which do the obvious
+\item \sym{pluginCtrlVal}, \sym{setPluginCtrlVal}: the first
+ returns the current value according to the \sym{{\_}controller}
+ list, the second only sets the \sym{curVal}, but does not
+ insert any events.
+\end{itemize}
+
+Whenever a \sym{CtrlList} has been manipulated,
+\sym{MusEGlobal::song->controllerChange(Track{*})} shall be called,
+which emits the \sym{MusEGlobal::song->controllerChanged(Track{*})}
+signal in order to inform any parts of MusE about the change (currently,
+only the arranger's part canvas utilizes this).
+
+\paragraph{Enabling and disabling controllers}
+Disabling the controller is both dependent from the current automation
+mode and from whether the GUI is native or not.
+In \usym{AUTO{\_}WRITE} mode, once a slider is touched (for MusE-GUIs) or
+once a OSC control change is received (for native GUIs), the control
+is disabled until the song is stopped or seeked.
+
+In \usym{AUTO{\_}TOUCH} (and currently (r1492) \usym{AUTO{\_}READ}, but
+that's to be fixed) mode, once a MusE-GUI's slider is pressed down, the
+corresponding control is disabled. Once the slider is released, the
+control is re-enabled again. Checkboxes remain in "disabled" mode,
+however they only affect the recorded automation until the last toggle
+of the checkbox. (Example: start the song, toggle the checkbox, toggle
+it again, wait 10 seconds, stop the song. This will NOT overwrite the
+last 10 seconds of automation data, but everything between the first
+and the last toggle.). For native GUIs, this is a bit tricky, because
+we don't have direct access to the GUI widgets. That is, we have no
+way to find out whether the user doesn't touch a control at all, or
+whether he has it held down, but just doesn't operate it. The current
+behaviour for native GUIs is to behave like in \usym{AUTO{\_}WRITE} mode.
+
+The responsible functions are: \sym{PluginI::oscControl} and
+\sym{DssiSynthIF::oscControl} for handling native GUIs,
+\sym{PluginI::ctrlPressed} and \sym{ctrlReleased} for MusE
+default GUIs and \sym{PluginI::guiParamPressed},
+\sym{guiParamReleased}, \sym{guiSliderPressed} and
+\sym{guiSliderReleased} for MusE GUIs read from a UI file;
+\sym{guiSlider{*}} obviously handle sliders, while \sym{guiParam{*}}
+handle everything else which is not a slider. They call
+\sym{PluginI::enableController} to enable/disable it.
+
+Furthermore, on every song stop or seek, \sym{PluginI::enableAllControllers}
+is called, which re-enables all controllers again. The call paths for
+this are:
+\begin{itemize}
+\item For stop: \sym{Song::stopRolling} calls
+ \sym{Song::processAutomationEvents} calls
+ \sym{Song::clearRecAu{\-}to{\-}ma{\-}tion} calls
+ \sym{Track::clearRecAutomation} calls
+ \sym{PluginI::enableAllControllers}
+\item For seek: \sym{Audio::seek} sends a message ("\sym{G}") to
+ \sym{Song::seqSignal} which calls
+ \sym{Song::clearRecAutomation} which calls
+ \sym{PluginI::enableAllControllers}
+\end{itemize}
+
+
+
+
+\chapter{Design decisions}
+\section{Automation}
+As of revision 1490, automation is handled in two ways: User-generated
+(live) automation data (generated by the user moving sliders while playing)
+is fed into \sym{PluginI::{\_}controlFifo}. Automation data is kept
+in \sym{AudioTrack::{\_}controller}, which is a \sym{CtrlListList},
+that is, a list of \sym{CtrlList}s, that is, a list of lists of
+controller-objects which hold the control points of the automation graph.
+The \sym{CtrlList} also stores whether the list is meant discrete
+(a new control point results in a value-jump) or continous (a new control
+point results in the value slowly sloping to the new value).
+
+While \sym{PluginI::{\_}controlFifo} can be queried very quickly and
+thus is processed with a very high resolution (only limited by the
+minimum control period setting), the automation value are expensive to
+query, and are only processed once in an audio \emph{driver} period.
+This might lead to noticeable jumps in value.
+
+This could possibly be solved in two ways:
+\paragraph{Maintaining a slave control list}
+This approach would maintain a fully redundant slave control list,
+similar to \sym{PluginI::{\_}controlFifo}. This list must be updated
+every time any automation-related thing is changed, and shall contain
+every controller change as a tuple of controller number and value.
+This could be processed in the same loop as \sym{PluginI::{\_}controlFifo},
+making it comfortable to implement; furthermore, it allows to cleanly
+offer automation-settings at other places in future (such as storing
+automation data in parts or similar).
+
+\paragraph{Holding iterators}
+We also could hold a list of iterators of the single \sym{CtrlList}s.
+This would also cause low CPU usage, because usually, the iterators only
+need to be incremented once. However, it is pretty complex to implement,
+because the iterators may become totally wrong (because of a seek in the
+song), and we must iterate through a whole list of iterators.
+
+\paragraph{Just use the current data access functions}
+By just using the current functions for accessing automation data,
+we might get a quick-and-dirty solution, which however wastes way too
+much CPU ressources. This is because on \emph{every single frame}, we
+need to do a binary search on multiple controller lists.
+
+
+\chapter{Feature requests}
+\section{Per-Part automation and more on automation} % by flo
+Automation shall be undo-able. Automation shall reside in parts which
+are exchangeable, clonable etc (like the MIDI- and Wave-Parts).
+Global per-synth/per-audiotrack automation shall also be available, but
+this can also be implemented as special case of part automation (one
+long part).
+
+\section{Pre-Rendering tracks}
+\subsection{The feature}
+All tracks shall be able to be "pre-renderable". Pre-rendering shall
+be "layered". Pre-rendering shall act like a transparent audio cache:
+Audio data is (redundantly) stored, wasting memory in order to save CPU.
+
+That is: Each track owns one or more wave-recordings of the length of
+the song. If the user calls "pre-render" on a track, then this track
+is played quasi-solo (see below), and the raw audio data is recorded
+and stored in the "layer 0" wave recording. If the user has any effects
+set up to be applied, then each effect is applied on a different layer
+(creating layer 1, layer 2 etc).
+
+This means, that also MIDI and drum tracks can have effects (which
+usually only operate on audio, but we HAVE audio data because of this
+prerendering).
+
+Furthermore, MusE by default does not send MIDI events to the synthesizers
+but instead just plays back the last layer of the prerecording (for
+MIDI tracks), or does not pipe the audio data through the whole plugin
+chain (causing cpu usage), but instead just plays back the last layer.
+The hearable result shall be the same.
+
+Once the user changes any parameter (automation data or plugins for
+wave tracks, MIDI events or effect plugin stuff for MIDI tracks),
+then MusE shall generate the sound for this particular track in the
+"old" way (send MIDI data to synthes, or pipe audio data through plugins).
+(So that the user will not even notice that MusE actually pre-renderered
+stuff.) Either MusE automatically records this while playback (if possible)
+or prompts the user to accordingly set up his cabling and then record
+it. Or (temporarily) disables prerecording for this track, falling back
+to the plain old way of generating sound.
+
+\emph{Quasi-solo} means: For wave tracks, just solo the track. For MIDI
+tracks, mute all tracks which are not on the same synth (channel?),
+and mute all \emph{note} events which are not on the quasi-soloed track.
+This causes MusE to still play any controller events from different
+tracks, because they might have effects on the quasi-soloed track. (You
+can have notes on channel 1 on one track and controller stuff on channel
+1 on another track; then you would need quasi-solo to get proper results.)
+
+\subsection{Use cases}
+\paragraph{Saving CPU}
+On slow systems, this is neccessary for songs with lots of, or demanding
+(or both) soft synthes / plugins. Even if the synth or plugin is so
+demanding that your system is not able to produce sound in real-time,
+then with this feature you'll be able to use the synth (this will make
+editing pretty laggish, because for a change you need to re-render at
+least a part before you can listen to it, but better than being unable
+to use the synth at all!)
+
+\paragraph{Exporting as audio project}
+Using pre-rendering on all tracks, you easily can export your project
+as multi-track audio file (for use with Ardour or similar DAWs).
+Just take the last layer of each track, and write the raw audio data
+into the file, and you're done. (Maybe we are even able to write down
+the raw-raw layer0 audio data plus information about used plugins and
+settings etc..?)
+
+\paragraph{Mobile audio workstations}
+You might want to work a bit on your audio projects on your notebook
+while you're not at home, not having access to your hardware synthesizers.
+Using this feature, you could have pre-recorded the stuff in your studio
+before, and now can at least fiddle around with the non-hw-synth-dependent
+parts of your song, while still having your \emph{full} song with you.
+
+\paragraph{Applying effects on MIDI tracks}
+If you have many physical audio inputs, you might already be able to
+apply effect chains on MIDI tracks, by wiring the synthes' audio
+outputs to your soundcard's inputs, and applying the effects on
+dedicated input tracks you have to create. This requires you to have
+expensive hardware, and is pretty complicated, because you need one
+additional track per MIDI synth.
+
+This feature allows you to apply effects on single MIDI tracks, and not
+only on full MIDI synthes, and doesn't require you to be have that
+many physical audio inputs (you need to manually replug your synthes,
+however).
+
+\subsection{Possible scenarios}
+\paragraph{Setting it up}
+Create a wave track, MusE will allow you to set or unset prerendering
+for every plugin in the plugin rack (recording the actual track is
+useless because it would be a plain copy).
+Create a MIDI track, MusE will ask you on which physical audio input
+your synth is connected. Setting up multiple synthes on one physical
+audio in is allowed, see below.
+
+\paragraph{Pre-rendering stuff}
+When the user presses the "pre-render" button, all tracks which have
+been changed since their last pre-rendering will be re-rendered.
+If you have multiple hardware synthes set up as they were connected
+to one physical audio input port, MusE will prompt you to first plug
+the proper cable in.
+
+\paragraph{Making changes}
+Change a note in a MIDI part, move or delete a part or change automation
+parameters. MusE will temporarily disable the pre-rendered information
+and instead generate the sound via sending out MIDI events, piping stuff
+through effect chains or similar. If you play back the whole song, or
+if you manually trigger a re-rendering of a track via the context menu,
+MusE will play back the stuff, record it again and re-enable the
+pre-rendered information.
+
+
+\subsection{Extensions}
+\paragraph{Automatic discovery of physical audio connections}
+The user plugs all (or only some) synthes' audio outs into the available
+audio inputs, then runs automatic discovery. This will send MIDI events
+to each synthesizer, and look on which audio in there's activity. Then
+it will assume that the synthesizer is connected to that particular
+audio in. Audio ins which show activity before any MIDI events were
+sent are not considered, as they're probably connected to microphones
+or other noise-generating non-synthes.
+
+\paragraph{Audio export}
+As described in the Use cases, MusE can allow you to export your song
+in some multitrack audio format.
+
+\paragraph{Cheap/Faked changes}
+For expensive or unavailable synthes, changing the Volume midi controller,
+the Pan controller or similar "easy" controllers will not trigger a
+complete re-rendering, but instead "fake" the change, by changing
+the volume data directly on the recorded wave. This might require some
+learning and might even get pretty complicated.
+
+\paragraph{Intelligent re-recording}
+For tiny changes, MusE shall only re-render the relevant part. If you
+change some MIDI notes, then begin re-recording shortly before the
+changes, and end re-recording as soon as the recorded stuff doesn't
+differ to much from the stuff coming from the synth. Then properly
+blend the old recording with the updated part.
+
+
+
+\section{Slotted editors}
+Currently, MusE has the pianoroll editor, drum editor, score editor,
+then the controller editor which is inside the pianoroll/drum editor.
+All these editors have a very similar concept: the "time axis" is
+vertical and (almost) linear, they handle parts, and events are
+manipulated similarly.
+
+A unified editor shall be created which allows you to combine different
+kinds of editors in one window, properly aligned against each other.
+These "different kinds of editors" shall be handled as "slots"; one
+unified editor window consists of:
+\begin{itemize}
+\item A menu bar, containing stuff suitable for the complete window,
+ which might include window name, MDI-ness etc.
+\item A toolbar which contains controls suitable for every single slot.
+\item A container with one or more slots; the slots can be scrolled in
+ y-direction if there are multipe slots.
+\item A time-scrollbar with zoom
+\end{itemize}
+
+Each slot contains the following:
+\begin{itemize}
+\item A menu button, button box or control panel for setting up this
+ particular slot. This could contain "note head colors", "show
+ a transposing instrument" etc for score edit slots, "event
+ rectangle color", "grid size" and "snap to grid" for pianoroll/
+ drum editors.
+\item The actual canvas
+\item A y-direction scroll bar, possibly with zoom control (for
+ pianoroll editor)
+\end{itemize}
+
+The main window does not show its scroll bar if there is only one slot,
+because the slot's scrollbar is sufficient then.
+
+Slots can be added, destroyed, moved around, maybe even merged (if the
+slot types allow it); basically, you can compare them with the staves
+in the score editor.
+
+The slots shall align against each other, that is, if a score editor
+slot displays a key change with lots of accidentials, then all other
+slots shall either also display the key change (if they're score slots)
+or display a gap. Events which happen at the same time shall be at the
+same x-coordinate, regardless which slot they are.
+
+\section{Controller master values}
+All controllers (MIDI-controllers and also automation controllers)
+shall have one set of "master values" which allow you to set a gain and
+a bias. Instead of the actual set value, $\textrm{value} * \textrm{bias}
++ textrm{bias}$ shall be sent to the MIDI device / the plugin. For
+controllers like "pan", the unbiased values shall be transformed, that
+is, a pan of 64, with $\textrm{bias}=2$ and $\textrm{gain}=0.5$, shall
+be transformed to 66 (because 64 is actually 0, while 0 is actually -64).
+These values shall be set in the arranger and whereever the actual
+controller/automation values can be edited.
+
+\section{Enabled-indicator while recording}
+The MusE-plugin-GUIs shall display a small LED displaying whether a
+controller is currently enabled or disabled. By clicking this LED, the
+enabled state shall be switched.
+
+Furthermore, there shall be a dedicated window which only lets you switch
+enabled/disabled states. This will be useful when using external GUIs
+or the MIDI-controller-to-automation feature, to re-enable a controller
+when in \usym{AUTO{\_}TOUCH} mode.
+
+
+
+\section{Linear automation editing}
+While holding some modifier key (like shift), operating the MusE-native-
+GUI sliders shall only generate control points when clicking and when
+releasing the slider. This will result in linear graphs for continous
+controllers, and in large steps for discrete controllers (which is in
+particular useful for stuff like "which low/high-pass filter type to use").
+
+Maybe make this behaviour default for discrete controllers?
+
+\section{Symbolic names for MIDI ports} \label{symbolic_ports}
+MIDI ports shall have a user-defined symbolic name (like "Korg" or "Yamaha DX 7").
+The mapping between these symbolic names and the hardware port (like
+"ALSA midi out port") is stored in the global configuration.
+
+Song files only specify the symbolic names as the ports associated with
+their tracks. No information about physical devices/port names, but only
+symbolic names are stored in the song file.
+
+This resolves the issues mentioned in \ref{portconfig_sucks}, and also
+allows the user to share his pieces with other people: They would only
+have to set up that symbolic-to-hardware mapping once (collisions are
+unlikely, because an equal symbolic name should usually mean the same
+device) and are happy, instead of having to re-map \emph{every} port
+for \emph{every} song.
+
+\end{document}
+
+% TODO: song type etc? kill it!
+% song len box: same
+
+% TODO: unified automation and midi ctrls:
+% both shall be editable through the same editors
+% four modes: 1. discrete
+% 2. continous (plus a global and per-port setting for the max rate)
+% 3. switch (not necessarily ON/OFF; signals with color plus text annotation)
+% 4. raw (no graph, instead a box with the value sent out (for "all voices off")
+% they shall be copy-and-pastable, at least between compatible modes
+% they shall be slotted, like pianoroll
+% maybe also "overlapping", like arranger (?)
+% midi recording tries to make out straight lines (like non-ended automation streams)
+%
+
+
+% new song (in general: load as template) plus "overwrite port config"
+% should re-create the default jack devices and autoconnect them.
+
+% what's audio aux for?
+
+% bug in arranger/pcanvas/automation: if a controlpoint is directly on
+% a line of another ctrl graph, you can't click it
+