summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandros Theodotou <alex@zrythm.org>2019-08-29 17:12:43 +0100
committerAlexandros Theodotou <alex@zrythm.org>2019-08-29 17:12:43 +0100
commit76ae6dd2c808aab6343e063f42a281a96d172771 (patch)
treec13c7b13c3e03be183242bc696ad92bd9c2e528c
parent7b86de9405c9a3268cfb0eedcba926b9917d93fd (diff)
downloadzrythm-76ae6dd2c808aab6343e063f42a281a96d172771.zip
zrythm-76ae6dd2c808aab6343e063f42a281a96d172771.tar.gz
zrythm-76ae6dd2c808aab6343e063f42a281a96d172771.tar.bz2
huge refactor of signal flow
-rw-r--r--THANKS13
-rw-r--r--TRANSLATORS3
-rw-r--r--inc/audio/channel.h56
-rw-r--r--inc/audio/engine.h89
-rw-r--r--inc/audio/engine_alsa.h9
-rw-r--r--inc/audio/engine_jack.h18
-rw-r--r--inc/audio/engine_pa.h15
-rw-r--r--inc/audio/ext_port.h184
-rw-r--r--inc/audio/port.h84
-rw-r--r--inc/audio/routing.h2
-rw-r--r--inc/gui/widgets/inspector_track.h12
-rw-r--r--inc/gui/widgets/track_properties_expander.h (renamed from inc/gui/widgets/instrument_track_info_expander.h)30
-rw-r--r--resources/ui/inspector_track.ui2
-rw-r--r--src/audio/channel.c257
-rw-r--r--src/audio/engine.c91
-rw-r--r--src/audio/engine_alsa.c140
-rw-r--r--src/audio/engine_dummy.c53
-rw-r--r--src/audio/engine_jack.c376
-rw-r--r--src/audio/engine_pa.c45
-rw-r--r--src/audio/ext_port.c222
-rw-r--r--src/audio/fader.c11
-rw-r--r--src/audio/meson.build1
-rw-r--r--src/audio/port.c576
-rw-r--r--src/audio/routing.c206
-rw-r--r--src/audio/track.c38
-rw-r--r--src/gui/widgets/channel.c9
-rw-r--r--src/gui/widgets/inspector_track.c21
-rw-r--r--src/gui/widgets/live_waveform.c6
-rw-r--r--src/gui/widgets/meson.build2
-rw-r--r--src/gui/widgets/track_properties_expander.c (renamed from src/gui/widgets/instrument_track_info_expander.c)26
30 files changed, 1781 insertions, 816 deletions
diff --git a/THANKS b/THANKS
index 51c96b4..f8298e3 100644
--- a/THANKS
+++ b/THANKS
@@ -6,16 +6,23 @@ Thanks:
* Help with GSource-related fixes
* Help with optimization
Adam Kosmin
- * UI ideas
+ * UI/feature ideas
* Financial contribution
+ * Bug reports
+ Milk
+ * UI/feature ideas
+ * Bug reports
bill-auger
* Coming up with the Zrythm tagline
- Yuri
- * FreeBSD packager
+ * Packaging advice
Robin Gareus <https://gareus.org/>
* Help and advice
* Routing algorithm
* Latency compensation algorithm
+ The GTK team
+ * Assistance with GTK-related code
+ LAD
+ * Assistance with LV2 and audio-related code
----
diff --git a/TRANSLATORS b/TRANSLATORS
index ae67f0d..081ad14 100644
--- a/TRANSLATORS
+++ b/TRANSLATORS
@@ -17,6 +17,9 @@ Norwegian Bokmal:
Polish:
* WaldiS <admin@sto.ugu.pl>
+Portuguese:
+ * Silvério Santos <ssantos@web.de>
+
----
Copyright (C) 2019 Alexandros Theodotou
diff --git a/inc/audio/channel.h b/inc/audio/channel.h
index 6311ac8..12b206d 100644
--- a/inc/audio/channel.h
+++ b/inc/audio/channel.h
@@ -59,6 +59,7 @@
typedef struct _ChannelWidget ChannelWidget;
typedef struct Track Track;
typedef struct _TrackWidget TrackWidget;
+typedef struct ExtPort ExtPort;
/**
* A Channel is part of a Track (excluding Tracks that
@@ -98,10 +99,46 @@ typedef struct Channel
int num_ats;
int ats_size;
+ /**
+ * External MIDI inputs that are currently
+ * connected to this channel as official inputs,
+ * unless all_midi_ins is enabled.
+ *
+ * These should be serialized every time and
+ * if all_midi_ins is not enabled, connected to
+ * when the project gets loaded.
+ *
+ * If all_midi_ins is enabled, these are ignored.
+ */
+ ExtPort * ext_midi_ins[32];
+ int num_ext_midi_ins;
+
+ /** If 1, the channel will connect to all MIDI ins
+ * found. */
+ int all_midi_ins;
+
+ /**
+ * 1 or 0 flags for each channel to enable it or
+ * disable it.
+ *
+ * If all_midi_channels is enabled, this is
+ * ignored.
+ */
+ int midi_channels[16];
+
+ /** If 1, the channel will accept MIDI messages
+ * from all MIDI channels.
+ */
+ int all_midi_channels;
+
/** The channel fader. */
Fader fader;
- /** Prefader. */
+ /**
+ * Prefader.
+ *
+ * The last plugin should connect to this.
+ */
PassthroughProcessor prefader;
/**
@@ -121,26 +158,27 @@ typedef struct Channel
*
* This port is for receiving MIDI signals from
* an external MIDI source.
+ *
+ * This is also where piano roll, midi in and midi
+ * manual press will be routed to and this will
+ * be the port used to pass midi to the plugins.
*/
Port * midi_in;
/**
* MIDI output for sending MIDI signals to other
- * destinations.
+ * destinations, such as other channels when
+ * directly routed (eg MIDI track to ins track).
*/
Port * midi_out;
/** Flag used while processing. */
int filled_stereo_in_bufs;
-
/*
- * The last plugin should connect to this.
- *
- * Plugins are processed slot-by-slot, and if
- * nothing is connected here it will simply
- * remain an empty buffer, i.e., channel will
- * produce no sound.
+ * Ports for direct (track-to-track) routing with
+ * the exception of master, which will route the
+ * output to monitor in.
*/
StereoPorts * stereo_out;
diff --git a/inc/audio/engine.h b/inc/audio/engine.h
index 56a6b80..2db109a 100644
--- a/inc/audio/engine.h
+++ b/inc/audio/engine.h
@@ -51,6 +51,7 @@ typedef struct Port Port;
typedef struct Channel Channel;
typedef struct Plugin Plugin;
typedef struct Tracklist Tracklist;
+typedef struct ExtPort ExtPort;
/**
* @defgroup audio Audio
@@ -117,7 +118,8 @@ typedef struct AudioEngine
long cycle;
#ifdef HAVE_JACK
- jack_client_t * client; ///< jack client
+ /** JACK client. */
+ jack_client_t * client;
/**
* Whether transport master/client or no
@@ -139,20 +141,49 @@ typedef struct AudioEngine
Mixer mixer; ///< the mixer
/**
- * To be serialized instead of StereoPorts.
+ * Audio intefrace outputs (only 2 are used).
+ *
+ * These should be initialized at the start and
+ * only used at runtime for getting the buffers.
+ *
+ * They should eventually be stored in GSettings
+ * since they are user settings and not project
+ * related.
*/
+ ExtPort * hw_stereo_outs[16];
+ int num_hw_stereo_outs;
- /** stereo in ports from the backend. */
- StereoPorts * stereo_in;
+ /**
+ * Audio intefrace inputs (only 2 are used).
+ *
+ * These should be initialized at the start and
+ * only used at runtime for getting the buffers.
+ *
+ * They should eventually be stored in GSettings
+ * since they are user settings and not project
+ * related.
+ *
+ * They should only be used in audio tracks as
+ * default recording input.
+ */
+ ExtPort * hw_stereo_ins[16];
+ int num_hw_stereo_ins;
- /** stereo out ports to the backend. */
- StereoPorts * stereo_out;
+ /** MIDI Clock in TODO. */
+ Port * midi_clock_in;
- /** MIDI in port from the audio engine. */
- Port * midi_in;
+ /**
+ * Monitor fader.
+ *
+ * The Master stereo out should connect to this.
+ */
+ Fader monitor_fader;
- /** MIDI out port from the audio engine. */
- Port * midi_out;
+ /**
+ * Monitor - these should be the last ports in
+ * the signal chain.
+ */
+ StereoPorts * monitor_out;
/**
* Flag to tell the UI that this channel had
@@ -164,7 +195,12 @@ typedef struct AudioEngine
*/
int trigger_midi_activity;
- /** Manual note prress in the piano roll. */
+ /**
+ * Manual note press in the piano roll.
+ *
+ * This should route to the post MIDI in of the
+ * applicable channel.
+ */
Port * midi_editor_manual_press;
/** Number of frames/samples in the current
@@ -268,18 +304,18 @@ engine_fields_schema[] =
"mixer", CYAML_FLAG_DEFAULT,
AudioEngine, mixer,
mixer_fields_schema),
- CYAML_FIELD_MAPPING_PTR (
- "stereo_in", CYAML_FLAG_POINTER,
- AudioEngine, stereo_in,
- stereo_ports_fields_schema),
- CYAML_FIELD_MAPPING_PTR (
- "stereo_out", CYAML_FLAG_POINTER,
- AudioEngine, stereo_out,
- stereo_ports_fields_schema),
- CYAML_FIELD_MAPPING_PTR (
- "midi_in", CYAML_FLAG_POINTER,
- AudioEngine, midi_in,
- port_fields_schema),
+ //CYAML_FIELD_MAPPING_PTR (
+ //"stereo_in", CYAML_FLAG_POINTER,
+ //AudioEngine, stereo_in,
+ //stereo_ports_fields_schema),
+ //CYAML_FIELD_MAPPING_PTR (
+ //"stereo_out", CYAML_FLAG_POINTER,
+ //AudioEngine, stereo_out,
+ //stereo_ports_fields_schema),
+ //CYAML_FIELD_MAPPING_PTR (
+ //"midi_in", CYAML_FLAG_POINTER,
+ //AudioEngine, midi_in,
+ //port_fields_schema),
CYAML_FIELD_MAPPING_PTR (
"midi_editor_manual_press", CYAML_FLAG_POINTER,
AudioEngine, midi_editor_manual_press,
@@ -352,6 +388,13 @@ void
engine_post_process ();
/**
+ * Called to fill in the external buffers at the end
+ * of the processing cycle.
+ */
+void
+engine_fill_out_bufs ();
+
+/**
* Closes any connections and free's data.
*/
void
diff --git a/inc/audio/engine_alsa.h b/inc/audio/engine_alsa.h
index abea793..29598c5 100644
--- a/inc/audio/engine_alsa.h
+++ b/inc/audio/engine_alsa.h
@@ -61,6 +61,15 @@ engine_alsa_prepare_process (
AudioEngine * self);
/**
+ * Fill the output buffers at the end of the
+ * cycle.
+ */
+void
+engine_alsa_fill_out_bufs (
+ AudioEngine * self,
+ int nframes);
+
+/**
* Sets up the audio engine to use alsa.
*/
int
diff --git a/inc/audio/engine_jack.h b/inc/audio/engine_jack.h
index c14a00a..94c3373 100644
--- a/inc/audio/engine_jack.h
+++ b/inc/audio/engine_jack.h
@@ -45,11 +45,19 @@ engine_jack_test (
GtkWindow * win);
/**
+ * Refreshes the list of external ports.
+ */
+void
+engine_jack_rescan_ports (
+ AudioEngine * self);
+
+/**
* Zero's out the output buffers.
*/
void
engine_jack_clear_output_buffers (
- AudioEngine * self);
+ AudioEngine * self,
+ int nframes);
/**
* Prepares for processing.
@@ -69,6 +77,14 @@ engine_jack_set_transport_type (
AudioEngineJackTransportType type);
/**
+ * Fills the external out bufs.
+ */
+void
+engine_jack_fill_out_bufs (
+ AudioEngine * self,
+ int nframes);
+
+/**
* Sets up the MIDI engine to use jack.
*
* @param loading Loading a Project or not.
diff --git a/inc/audio/engine_pa.h b/inc/audio/engine_pa.h
index 210236d..239d071 100644
--- a/inc/audio/engine_pa.h
+++ b/inc/audio/engine_pa.h
@@ -29,6 +29,12 @@
typedef struct AudioEngine AudioEngine;
/**
+ * @addtogroup audio
+ *
+ * @{
+ */
+
+/**
* Set up Port Audio.
*/
void
@@ -37,8 +43,9 @@ pa_setup (
int loading);
void
-engine_pa_fill_stereo_out_buffs (
- AudioEngine * engine);
+engine_pa_fill_out_bufs (
+ AudioEngine * engine,
+ int nframes);
/**
* This routine will be called by the PortAudio
@@ -81,6 +88,10 @@ engine_pa_test (
void
pa_terminate (AudioEngine * engine);
+/**
+ * @}
+ */
+
#endif
#endif // HAVE_PORT_AUDIO
diff --git a/inc/audio/ext_port.h b/inc/audio/ext_port.h
new file mode 100644
index 0000000..a4923fe
--- /dev/null
+++ b/inc/audio/ext_port.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2019 Alexandros Theodotou <alex at zrythm dot org>
+ *
+ * This file is part of Zrythm
+ *
+ * Zrythm is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Zrythm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AUDIO_EXT_PORT_H__
+#define __AUDIO_EXT_PORT_H__
+
+/**
+ * \file
+ *
+ * External ports.
+ */
+
+#include "config.h"
+
+#include "audio/automatable.h"
+#include "audio/fader.h"
+#include "audio/passthrough_processor.h"
+#include "plugins/plugin.h"
+#include "utils/audio.h"
+#include "utils/yaml.h"
+
+#include <gdk/gdk.h>
+
+#ifdef HAVE_JACK
+#include <jack/jack.h>
+#endif
+
+/**
+ * @addtogroup audio
+ *
+ * @{
+ */
+
+/**
+ * External port type.
+ */
+typedef enum ExtPortType
+{
+ EXT_PORT_TYPE_JACK,
+ EXT_PORT_TYPE_ALSA,
+} ExtPortType;
+
+/**
+ * External port.
+ */
+typedef struct ExtPort
+{
+ /** JACK port. */
+ jack_port_t * jport;
+
+ /** Full port name. */
+ char * full_name;
+
+ /** Short port name. */
+ char * short_name;
+
+ ExtPortType type;
+} ExtPort;
+
+static const cyaml_schema_field_t
+ext_port_fields_schema[] =
+{
+
+ CYAML_FIELD_END
+};
+
+static const cyaml_schema_value_t
+ext_port_schema =
+{
+ CYAML_VALUE_MAPPING (
+ CYAML_FLAG_POINTER,
+ ExtPort, ext_port_fields_schema),
+};
+
+/**
+ * Inits the ExtPort after loading a project.
+ */
+void
+ext_port_init_loaded (
+ ExtPort * ext_port);
+
+/**
+ * Returns the buffer of the external port.
+ */
+float *
+ext_port_get_buffer (
+ ExtPort * ext_port,
+ int nframes);
+
+/**
+ * Clears the buffer of the external port.
+ */
+void
+ext_port_clear_buffer (
+ ExtPort * ext_port,
+ int nframes);
+
+/**
+ * Exposes the given Port if not exposed and makes
+ * the connection from the Port to the ExtPort (eg in
+ * JACK) or backwards.
+ *
+ * @param src 1 if the ext_port is the source, 0 if it
+ * is the destination.
+ */
+void
+ext_port_connect (
+ ExtPort * ext_port,
+ Port * port,
+ int src);
+
+/**
+ * Disconnects the Port from the ExtPort.
+ *
+ * @param src 1 if the ext_port is the source, 0 if it
+ * is the destination.
+ */
+void
+ext_port_disconnect (
+ ExtPort * ext_port,
+ Port * port,
+ int src);
+
+#ifdef HAVE_JACK
+/**
+ * Creates an ExtPort from a JACK port.
+ */
+ExtPort *
+ext_port_from_jack_port (
+ jack_port_t * jport);
+#endif
+
+/**
+ * Collects external ports of the given type.
+ *
+ * @param hw Hardware or not.
+ * @param ports An array of ExtPort pointers to fill
+ * in. The array should be preallocated.
+ * @param size Size of the array to fill in.
+ */
+void
+ext_ports_get (
+ PortType type,
+ PortFlow flow,
+ int hw,
+ ExtPort ** ports,
+ int * size);
+
+/**
+ * Frees an array of ExtPort pointers.
+ */
+void
+ext_ports_free (
+ ExtPort ** ext_port,
+ int size);
+
+/**
+ * Frees the ext_port.
+ */
+void
+ext_port_free (
+ ExtPort * ext_port);
+
+/**
+ * @}
+ */
+
+#endif
diff --git a/inc/audio/port.h b/inc/audio/port.h
index 51bd19e..ac1eac4 100644
--- a/inc/audio/port.h
+++ b/inc/audio/port.h
@@ -29,6 +29,10 @@
#include "utils/yaml.h"
+#ifdef HAVE_JACK
+#include <jack/jack.h>
+#endif
+
typedef struct Plugin Plugin;
typedef struct MidiEvents MidiEvents;
typedef struct Fader Fader;
@@ -84,7 +88,13 @@ typedef enum PortOwnerType
PORT_OWNER_TYPE_PLUGIN,
PORT_OWNER_TYPE_TRACK,
PORT_OWNER_TYPE_PREFADER,
+
+ /* track fader */
PORT_OWNER_TYPE_FADER,
+
+ /* monitor fader */
+ PORT_OWNER_TYPE_MONITOR_FADER,
+
PORT_OWNER_TYPE_SAMPLE_PROCESSOR,
} PortOwnerType;
@@ -123,9 +133,18 @@ flags_bitvals[] =
typedef enum PortInternalType
{
INTERNAL_NONE,
- INTERNAL_LV2_PORT, ///< Lv2Port
- INTERNAL_JACK_PORT, ///< jack_port_t
- INTERNAL_PA_PORT, ///< port audio
+
+ /** Pointer to Lv2Port. */
+ INTERNAL_LV2_PORT,
+
+ /** Pointer to jack_port_t. */
+ INTERNAL_JACK_PORT,
+
+ /** TODO */
+ INTERNAL_PA_PORT,
+
+ /** Pointer to snd_seq_port_info_t. */
+ INTERNAL_ALSA_SEQ_PORT,
} PortInternalType;
typedef struct Lv2Port Lv2Port;
@@ -481,7 +500,8 @@ stereo_ports_init_loaded (StereoPorts * sp);
* Creates port.
*/
Port *
-port_new (char * label);
+port_new (
+ const char * label);
/**
* Creates port.
@@ -490,7 +510,7 @@ Port *
port_new_with_type (
PortType type,
PortFlow flow,
- char * label);
+ const char * label);
/**
* Creates port and adds given data to it.
@@ -503,8 +523,8 @@ port_new_with_data (
PortInternalType internal_type,
PortType type,
PortFlow flow,
- char * label,
- void * data);
+ const char * label,
+ void * data);
/**
* Creates blank stereo ports.
@@ -527,6 +547,18 @@ stereo_ports_new_generic (
void * owner);
/**
+ * Connects the internal ports using
+ * port_connect().
+ *
+ * @param locked Lock the connection.
+ */
+void
+stereo_ports_connect (
+ StereoPorts * src,
+ StereoPorts * dest,
+ int locked);
+
+/**
* Receives MIDI data from the port's exposed
* JACK port (if any) into the port.
*/
@@ -653,6 +685,18 @@ port_get_multiplier_by_index (
void
port_free (Port * port);
+/**
+ * Sets whether to expose the port to the backend
+ * and exposes it or removes it.
+ *
+ * It checks what the backend is using the engine's
+ * audio backend or midi backend settings.
+ */
+void
+port_set_expose_to_backend (
+ Port * self,
+ int expose);
+
#ifdef HAVE_JACK
/**
* Sets whether to expose the port to JACk and
@@ -662,6 +706,32 @@ void
port_set_expose_to_jack (
Port * self,
int expose);
+
+/**
+ * Returns the JACK port attached to this port,
+ * if any.
+ */
+jack_port_t *
+port_get_internal_jack_port (
+ Port * port);
+
+#endif
+
+#ifdef __linux__
+
+/**
+ * Returns the Port matching the given ALSA
+ * sequencer port ID.
+ */
+Port *
+port_find_by_alsa_seq_id (
+ const int id);
+
+void
+port_set_expose_to_alsa (
+ Port * self,
+ int expose);
+
#endif
/**
diff --git a/inc/audio/routing.h b/inc/audio/routing.h
index 5efe8d9..f92d3a4 100644
--- a/inc/audio/routing.h
+++ b/inc/audio/routing.h
@@ -53,6 +53,8 @@ typedef enum GraphNodeType
ROUTE_NODE_TYPE_PLUGIN,
/** Fader/pan processor. */
ROUTE_NODE_TYPE_FADER,
+ /** Fader/pan processor for monitor. */
+ ROUTE_NODE_TYPE_MONITOR_FADER,
/** Pre-Fader passthrough processor. */
ROUTE_NODE_TYPE_PREFADER,
/** Sample processor. */
diff --git a/inc/gui/widgets/inspector_track.h b/inc/gui/widgets/inspector_track.h
index 511a887..d80cf2f 100644
--- a/inc/gui/widgets/inspector_track.h
+++ b/inc/gui/widgets/inspector_track.h
@@ -32,21 +32,21 @@ G_DECLARE_FINAL_TYPE (InspectorTrackWidget,
typedef struct TracklistSelections
TracklistSelections;
-typedef struct _InstrumentTrackInfoExpanderWidget
- InstrumentTrackInfoExpanderWidget;
+typedef struct _TrackPropertiesExpanderWidget
+ TrackPropertiesExpanderWidget;
typedef struct _PortsExpanderWidget
PortsExpanderWidget;
typedef struct _InspectorTrackWidget
{
GtkBox parent_instance;
- InstrumentTrackInfoExpanderWidget *
+ TrackPropertiesExpanderWidget *
instrument_track_info;
PortsExpanderWidget * sends;
- PortsExpanderWidget * stereo_in;
- PortsExpanderWidget * midi_in;
- PortsExpanderWidget * midi_out;
+ //PortsExpanderWidget * stereo_in;
+ //PortsExpanderWidget * midi_in;
+ //PortsExpanderWidget * midi_out;
} InspectorTrackWidget;
void
diff --git a/inc/gui/widgets/instrument_track_info_expander.h b/inc/gui/widgets/track_properties_expander.h
index 2098e90..f4d214f 100644
--- a/inc/gui/widgets/instrument_track_info_expander.h
+++ b/inc/gui/widgets/track_properties_expander.h
@@ -19,27 +19,27 @@
/** \file */
-#ifndef __GUI_WIDGETS_INSTRUMENT_TRACK_INFO_EXPANDER_H__
-#define __GUI_WIDGETS_INSTRUMENT_TRACK_INFO_EXPANDER_H__
+#ifndef __GUI_WIDGETS_TRACK_PROPERTIES_EXPANDER_H__
+#define __GUI_WIDGETS_TRACK_PROPERTIES_EXPANDER_H__
#include "gui/widgets/two_col_expander_box.h"
#include <gtk/gtk.h>
-#define INSTRUMENT_TRACK_INFO_EXPANDER_WIDGET_TYPE \
- (instrument_track_info_expander_widget_get_type ())
+#define TRACK_PROPERTIES_EXPANDER_WIDGET_TYPE \
+ (track_properties_expander_widget_get_type ())
G_DECLARE_FINAL_TYPE (
- InstrumentTrackInfoExpanderWidget,
- instrument_track_info_expander_widget,
+ TrackPropertiesExpanderWidget,
+ track_properties_expander_widget,
Z,
- INSTRUMENT_TRACK_INFO_EXPANDER_WIDGET,
+ TRACK_PROPERTIES_EXPANDER_WIDGET,
TwoColExpanderBoxWidget);
typedef struct _EditableLabelWidget
EditableLabelWidget;
typedef struct Track Track;
-typedef struct _InstrumentTrackInfoExpanderWidget
+typedef struct _TrackPropertiesExpanderWidget
{
TwoColExpanderBoxWidget parent_instance;
@@ -53,24 +53,24 @@ typedef struct _InstrumentTrackInfoExpanderWidget
/* TODO midi inputs, etc. See Instrument Track
* Inspector from cubase manual. */
- /** Track the InstrumentTrackInfoExpanderWidget is
+ /** Track the TrackPropertiesExpanderWidget is
* associated with. */
Track * track;
-} InstrumentTrackInfoExpanderWidget;
+} TrackPropertiesExpanderWidget;
/**
* Refreshes each field.
*/
void
-instrument_track_info_expander_widget_refresh (
- InstrumentTrackInfoExpanderWidget * self);
+track_properties_expander_widget_refresh (
+ TrackPropertiesExpanderWidget * self);
/**
- * Sets up the InstrumentTrackInfoExpanderWidget.
+ * Sets up the TrackPropertiesExpanderWidget.
*/
void
-instrument_track_info_expander_widget_setup (
- InstrumentTrackInfoExpanderWidget * self,
+track_properties_expander_widget_setup (
+ TrackPropertiesExpanderWidget * self,
Track * track);
#endif
diff --git a/resources/ui/inspector_track.ui b/resources/ui/inspector_track.ui
index 1e7f01d..5dcfb4f 100644
--- a/resources/ui/inspector_track.ui
+++ b/resources/ui/inspector_track.ui
@@ -28,7 +28,7 @@
<property name="orientation">GTK_ORIENTATION_VERTICAL</property>
<property name="spacing">2</property>
<child>
- <object class="InstrumentTrackInfoExpanderWidget" id="instrument_track_info">
+ <object class="TrackPropertiesExpanderWidget" id="instrument_track_info">
<property name="visible">True</property>
</object>
</child>
diff --git a/src/audio/channel.c b/src/audio/channel.c
index 8e5900e..2bc2d70 100644
--- a/src/audio/channel.c
+++ b/src/audio/channel.c
@@ -75,10 +75,15 @@ disconnect_ch_input_from_fader (
ch->prefader.stereo_in->r);
break;
case TYPE_EVENT:
- port_disconnect (ch->midi_in, ch->midi_out);
- if (track_has_piano_roll (ch->track))
- port_disconnect (
- ch->piano_roll, ch->midi_out);
+ if (ch->track->out_signal_type ==
+ TYPE_EVENT)
+ {
+ port_disconnect (
+ ch->midi_in, ch->midi_out);
+ if (track_has_piano_roll (ch->track))
+ port_disconnect (
+ ch->piano_roll, ch->midi_out);
+ }
break;
default:
break;
@@ -1015,7 +1020,7 @@ channel_handle_recording (Channel * self)
/* convert MIDI data to midi notes */
MidiEvents * midi_events =
- AUDIO_ENGINE->midi_in->midi_events;
+ self->midi_in->midi_events;
if (midi_events->num_events > 0)
{
MidiNote * mn;
@@ -1126,6 +1131,13 @@ channel_prepare_process (Channel * self)
}
}
self->filled_stereo_in_bufs = 0;
+
+ /* copy the cached MIDI events to the MIDI events
+ * in the MIDI in port */
+ if (self->track->in_signal_type ==
+ TYPE_EVENT)
+ midi_events_dequeue (
+ self->midi_in->midi_events);
}
void
@@ -1311,10 +1323,12 @@ channel_connect (
ch->output_pos = -1;
port_connect (
ch->stereo_out->l,
- AUDIO_ENGINE->stereo_out->l, 1);
+ AUDIO_ENGINE->monitor_fader.stereo_in->l,
+ 1);
port_connect (
ch->stereo_out->r,
- AUDIO_ENGINE->stereo_out->r, 1);
+ AUDIO_ENGINE->monitor_fader.stereo_in->r,
+ 1);
}
else
{
@@ -1370,6 +1384,36 @@ channel_connect (
1);
}
}
+
+ /* expose ports to backend */
+ if (ch->track->in_signal_type ==
+ TYPE_AUDIO)
+ {
+ port_set_expose_to_backend (
+ ch->stereo_in->l , 1);
+ port_set_expose_to_backend (
+ ch->stereo_in->r , 1);
+ }
+ if (ch->track->in_signal_type ==
+ TYPE_EVENT)
+ {
+ port_set_expose_to_backend (
+ ch->midi_in , 1);
+ }
+ if (ch->track->out_signal_type ==
+ TYPE_AUDIO)
+ {
+ port_set_expose_to_backend (
+ ch->stereo_out->l , 1);
+ port_set_expose_to_backend (
+ ch->stereo_out->r , 1);
+ }
+ if (ch->track->out_signal_type ==
+ TYPE_EVENT)
+ {
+ port_set_expose_to_backend (
+ ch->midi_out , 1);
+ }
}
/**
@@ -1530,6 +1574,93 @@ channel_prepare_for_serialization (
}
/**
+ * Inits the stereo ports of the Channel while
+ * exposing them to the backend.
+ *
+ * This assumes the caller already checked that
+ * this channel should have the given ports
+ * enabled.
+ *
+ * @param in 1 for input, 0 for output.
+ * @param loading 1 if loading a channel, 0 if
+ * new.
+ */
+static void
+init_stereo_out_ports (
+ Channel * self,
+ int in,
+ int loading)
+{
+ char str[80];
+ strcpy (str, in ? "Stereo in" : "Stereo out");
+ Port * l, * r;
+ StereoPorts ** sp =
+ in ? &self->stereo_in : &self->stereo_out;
+ PortFlow flow = in ? FLOW_INPUT : FLOW_OUTPUT;
+
+ if (loading)
+ {
+ }
+ else
+ {
+ strcat (str, " L");
+ l = port_new_with_type (
+ TYPE_AUDIO,
+ flow,
+ str);
+
+ str[10] = '\0';
+ strcat (str, " R");
+ r = port_new_with_type (
+ TYPE_AUDIO,
+ flow,
+ str);
+ }
+
+ port_set_owner_track (
+ l, self->track);
+ port_set_owner_track (
+ r, self->track);
+
+ *sp =
+ stereo_ports_new_from_existing (
+ l, r);
+}
+
+/**
+ * Inits the MIDI In port of the Channel while
+ * exposing it to JACK.
+ *
+ * This assumes the caller already checked that
+ * this channel should have the given MIDI port
+ * enabled.
+ *
+ * @param in 1 for input, 0 for output.
+ * @param loading 1 if loading a channel, 0 if
+ * new.
+ */
+static void
+init_midi_port (
+ Channel * self,
+ int in,
+ int loading)
+{
+ char * str = in ? "MIDI in" : "MIDI out";
+ Port ** port =
+ in ? &self->midi_in : &self->midi_out;
+ PortFlow flow = in ? FLOW_INPUT : FLOW_OUTPUT;
+
+ *port =
+ port_new_with_type (
+ TYPE_EVENT,
+ flow,
+ str);
+
+ port_set_owner_track (
+ *port, self->track);
+}
+
+/**
* Creates a channel of the given type with the
* given label.
*/
@@ -1549,43 +1680,49 @@ channel_new (
sizeof (AutomationTrack *));
/* create ports */
- self->stereo_in =
- stereo_ports_new_generic (
- 1, _("Stereo in"),
- PORT_OWNER_TYPE_TRACK, track);
- self->stereo_out =
- stereo_ports_new_generic (
- 0, _("Stereo out"),
- PORT_OWNER_TYPE_TRACK, track);
-
- char * pll =
- g_strdup (_("MIDI in"));
- self->midi_in =
- port_new_with_type (
- TYPE_EVENT,
- FLOW_INPUT,
- pll);
- self->midi_in->midi_events =
- midi_events_new (
- self->midi_in);
- g_free (pll);
- pll =
- g_strdup (_("MIDI out"));
- self->midi_out =
- port_new_with_type (
- TYPE_EVENT,
- FLOW_OUTPUT,
- pll);
- self->midi_out->midi_events =
- midi_events_new (
- self->midi_out);
- g_free (pll);
- port_set_owner_track (
- self->midi_in,
- track);
- port_set_owner_track (
- self->midi_out,
- track);
+ char * str;
+ switch (track->in_signal_type)
+ {
+ case TYPE_EVENT:
+ init_midi_port (self, 1, 0);
+
+ /* set up piano roll port */
+ if (track_has_piano_roll (track))
+ {
+ str = _("Piano Roll");
+ self->piano_roll =
+ port_new_with_type (
+ TYPE_EVENT,
+ FLOW_INPUT,
+ str);
+ self->piano_roll->identifier.flags =
+ PORT_FLAG_PIANO_ROLL;
+ port_set_owner_track (
+ self->piano_roll,
+ track);
+ }
+ break;
+ case TYPE_AUDIO:
+ init_stereo_out_ports (
+ self, 1, 0);
+ break;
+ default:
+ break;
+ }
+
+ switch (track->out_signal_type)
+ {
+ case TYPE_AUDIO:
+ init_stereo_out_ports (
+ self, 0, 0);
+ break;
+ case TYPE_EVENT:
+ init_midi_port (
+ self, 0, 0);
+ break;
+ default:
+ break;
+ }
/* init plugins */
for (int i = 0; i < STRIP_SIZE; i++)
@@ -1606,26 +1743,6 @@ channel_new (
prefader_type,
self);
- /* set up piano roll port */
- char * tmp =
- g_strdup (_("Piano Roll"));
- self->piano_roll =
- port_new_with_type (
- TYPE_EVENT,
- FLOW_INPUT,
- tmp);
- self->piano_roll->identifier.flags =
- PORT_FLAG_PIANO_ROLL;
- self->piano_roll->identifier.owner_type =
- PORT_OWNER_TYPE_TRACK;
- self->piano_roll->identifier.track_pos =
- self->track->pos;
- self->piano_roll->track =
- self->track;
- self->piano_roll->midi_events =
- midi_events_new (
- self->piano_roll);
-
return self;
}
@@ -1728,17 +1845,17 @@ channel_disconnect_plugin_from_strip (
{
port = pl->in_ports[i];
- if (port->internal_type ==
- INTERNAL_JACK_PORT)
- port_set_expose_to_jack (port, 0);
+ if (port->internal_type !=
+ INTERNAL_NONE)
+ port_set_expose_to_backend (port, 0);
}
for (i = 0; i < pl->num_out_ports; i++)
{
port = pl->out_ports[i];
- if (port->internal_type ==
- INTERNAL_JACK_PORT)
- port_set_expose_to_jack (port, 0);
+ if (port->internal_type !=
+ INTERNAL_NONE)
+ port_set_expose_to_backend (port, 0);
}
}
diff --git a/src/audio/engine.c b/src/audio/engine.c
index ca43471..b149b5d 100644
--- a/src/audio/engine.c
+++ b/src/audio/engine.c
@@ -108,12 +108,15 @@ init_audio (
if (loading)
{
- stereo_ports_init_loaded (self->stereo_in);
- stereo_ports_init_loaded (self->stereo_out);
+ /*stereo_ports_init_loaded (self->stereo_in);*/
+ stereo_ports_init_loaded (self->monitor_out);
}
else
{
-
+ fader_init (
+ &self->monitor_fader,
+ FADER_TYPE_AUDIO_CHANNEL,
+ NULL);
}
}
@@ -235,6 +238,11 @@ engine_init (
break;
}
+ /* connect fader to monitor out */
+ stereo_ports_connect (
+ self->monitor_fader.stereo_out,
+ self->monitor_out, 1);
+
/* init midi */
init_midi (self, loading);
@@ -270,12 +278,9 @@ engine_init (
/* connect the sample processor to the engine
* output */
- port_connect (
- SAMPLE_PROCESSOR->stereo_out->l,
- self->stereo_out->l, 1);
- port_connect (
- SAMPLE_PROCESSOR->stereo_out->r,
- self->stereo_out->r, 1);
+ stereo_ports_connect (
+ SAMPLE_PROCESSOR->stereo_out,
+ self->monitor_out, 1);
}
void
@@ -362,13 +367,15 @@ audio_engine_close (AudioEngine * self)
*/
static void
clear_output_buffers (
- AudioEngine * self)
+ AudioEngine * self,
+ int nframes)
{
switch (self->audio_backend)
{
case AUDIO_BACKEND_JACK:
#ifdef HAVE_JACK
- engine_jack_clear_output_buffers (self);
+ engine_jack_clear_output_buffers (
+ self, nframes);
#endif
break;
default:
@@ -440,9 +447,10 @@ engine_process_prepare (
}
/* reset all buffers */
- port_clear_buffer (self->midi_in);
- port_clear_buffer (self->midi_out);
+ fader_clear_buffers (&self->monitor_fader);
port_clear_buffer (self->midi_editor_manual_press);
+ port_clear_buffer (self->monitor_out->l);
+ port_clear_buffer (self->monitor_out->r);
sample_processor_prepare_process (
&self->sample_processor, nframes);
@@ -506,22 +514,22 @@ receive_midi_events (
{
#ifdef HAVE_JACK
case MIDI_BACKEND_JACK:
- port_receive_midi_events_from_jack (
- self->midi_in, 0, nframes);
+ /*port_receive_midi_events_from_jack (*/
+ /*self->midi_in, 0, nframes);*/
break;
#endif
#ifdef __linux__
case MIDI_BACKEND_ALSA:
- engine_alsa_receive_midi_events (
- self, print);
+ /*engine_alsa_receive_midi_events (*/
+ /*self, print);*/
break;
#endif
default:
break;
}
- if (self->midi_in->midi_events->num_events > 0)
- self->trigger_midi_activity = 1;
+ /*if (self->midi_in->midi_events->num_events > 0)*/
+ /*self->trigger_midi_activity = 1;*/
}
/**
@@ -668,7 +676,7 @@ engine_process (
{
/* Clear output buffers just in case we have to
* return early */
- clear_output_buffers (self);
+ clear_output_buffers (self, _nframes);
if (!g_atomic_int_get (&self->run))
{
@@ -802,10 +810,18 @@ engine_process (
* To be called after processing for common logic.
*/
void
-engine_post_process (AudioEngine * self)
+engine_post_process (
+ AudioEngine * self)
{
zix_sem_post (&self->port_operation_lock);
+ if (!self->exporting)
+ {
+ /* fill in the external buffers */
+ engine_fill_out_bufs (
+ self, self->nframes);
+ }
+
/* stop panicking */
if (self->panic)
{
@@ -849,6 +865,39 @@ engine_post_process (AudioEngine * self)
}
/**
+ * Called to fill in the external output buffers at
+ * the end of the processing cycle.
+ */
+void
+engine_fill_out_bufs (
+ AudioEngine * self,
+ int nframes)
+{
+ switch (self->audio_backend)
+ {
+ case AUDIO_BACKEND_DUMMY:
+ break;
+ case AUDIO_BACKEND_ALSA:
+#ifdef __linux__
+ engine_alsa_fill_out_bufs (self, nframes);
+#endif
+ break;
+ case AUDIO_BACKEND_JACK:
+#ifdef HAVE_JACK
+ engine_jack_fill_out_bufs (self, nframes);
+#endif
+ break;
+ case AUDIO_BACKEND_PORT_AUDIO:
+#ifdef HAVE_PORT_AUDIO
+ engine_pa_fill_out_bufs (self, nframes);
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
+/**
* Closes any connections and free's data.
*/
void
diff --git a/src/audio/engine_alsa.c b/src/audio/engine_alsa.c
index 6988589..27db648 100644
--- a/src/audio/engine_alsa.c
+++ b/src/audio/engine_alsa.c
@@ -226,21 +226,34 @@ process_cb (
nframes);
}
+/**
+ * Called when an alsa MIDI event is received on
+ * any registered port.
+ */
static inline int
-midi_callback (
+on_midi_event (
AudioEngine* self)
{
snd_seq_event_t *ev;
-
- zix_sem_wait (
- &self->midi_in->midi_events->access_sem);
+ Port * port;
int time = 0;
do
{
+ /* get alsa seq event */
snd_seq_event_input (
self->seq_handle, &ev);
+
+ /* find the zrythm port by the alsa seq
+ * port ID */
+ port =
+ port_find_by_alsa_seq_id (
+ ev->dest.port);
+
+ zix_sem_wait (
+ &port->midi_events->access_sem);
+
switch (ev->type)
{
/* see https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_events.html for more */
@@ -248,7 +261,7 @@ midi_callback (
g_message ("pitch %d",
ev->data.control.value);
midi_events_add_pitchbend (
- self->midi_in->midi_events, 1,
+ port->midi_events, 1,
ev->data.control.value,
time++, 1);
break;
@@ -256,7 +269,7 @@ midi_callback (
g_message ("modulation %d",
ev->data.control.value);
midi_events_add_control_change (
- self->midi_in->midi_events,
+ port->midi_events,
1, ev->data.control.param,
ev->data.control.value,
time++, 1);
@@ -269,7 +282,7 @@ midi_callback (
/*ev->time.time.tv_sec,*/
/*ev->time.time.tv_nsec);*/
midi_events_add_note_on (
- self->midi_in->midi_events,
+ port->midi_events,
1, ev->data.note.note,
ev->data.note.velocity,
time++, 1);
@@ -278,7 +291,7 @@ midi_callback (
g_message ("note off: note %d",
ev->data.note.note);
midi_events_add_note_off (
- self->midi_in->midi_events,
+ port->midi_events,
1, ev->data.note.note,
time++, 1);
/* FIXME passing ticks, should pass
@@ -288,14 +301,15 @@ midi_callback (
g_message ("Unknown MIDI event received");
break;
}
+
+ zix_sem_post (
+ &port->midi_events->access_sem);
+
snd_seq_free_event(ev);
} while (
snd_seq_event_input_pending (
self->seq_handle, 0) > 0);
- zix_sem_post (
- &self->midi_in->midi_events->access_sem);
-
return 0;
}
@@ -330,6 +344,24 @@ engine_alsa_test (
return err;
}
+/**
+ * Fill the output buffers at the end of the
+ * cycle.
+ */
+void
+engine_alsa_fill_out_bufs (
+ AudioEngine * self,
+ int nframes)
+{
+ for (int i = 0; i < nframes; i++)
+ {
+ self->alsa_out_buf[i * 2] =
+ self->monitor_out->l->buf[i];
+ self->alsa_out_buf[i * 2 + 1] =
+ self->monitor_out->l->buf[i];
+ }
+}
+
static void *
audio_thread (void * _self)
{
@@ -422,12 +454,6 @@ midi_thread (void * _self)
snd_seq_set_client_name (
self->seq_handle, "Zrythm");
- if (snd_seq_create_simple_port (
- self->seq_handle, "Zrythm MIDI",
- SND_SEQ_PORT_CAP_WRITE |
- SND_SEQ_PORT_CAP_SUBS_WRITE,
- SND_SEQ_PORT_TYPE_APPLICATION) < 0)
- g_warning ("Error creating sequencer port");
int seq_nfds, l1;
struct pollfd *pfds;
@@ -447,7 +473,9 @@ midi_thread (void * _self)
for (l1 = 0; l1 < seq_nfds; l1++)
{
if (pfds[l1].revents > 0)
- midi_callback (self);
+ {
+ on_midi_event (self);
+ }
}
}
}
@@ -470,19 +498,6 @@ engine_alsa_prepare_process (
sizeof (float));
}
-/**
- * Copy the cached MIDI events to the MIDI events
- * in the MIDI in port, used at the start of each
- * cycle. */
-void
-engine_alsa_receive_midi_events (
- AudioEngine * self,
- int print)
-{
- midi_events_dequeue (
- self->midi_in->midi_events);
-}
-
int
alsa_setup (
AudioEngine *self, int loading)
@@ -494,41 +509,30 @@ alsa_setup (
(float *) malloc (
2 * sizeof (float) * self->block_length);
- Port *stereo_out_l, *stereo_out_r,
- *stereo_in_l, *stereo_in_r;
+ Port *monitor_out_l, *monitor_out_r;
- stereo_out_l =
+ /*const char * monitor_out_l_str =*/
+ /*"Monitor out L";*/
+ /*const char * monitor_out_r_str =*/
+ /*"Monitor out R";*/
+
+ monitor_out_l =
port_new_with_type (
TYPE_AUDIO, FLOW_OUTPUT,
- "ALSA Stereo Out / L");
- stereo_out_r =
+ "ALSA Monitor Out / L");
+ monitor_out_r =
port_new_with_type (
TYPE_AUDIO, FLOW_OUTPUT,
- "ALSA Stereo Out / R");
- stereo_in_l =
- port_new_with_type (
- TYPE_AUDIO, FLOW_INPUT,
- "ALSA Stereo In / L");
- stereo_in_r =
- port_new_with_type (
- TYPE_AUDIO, FLOW_INPUT,
- "ALSA Stereo In / R");
+ "ALSA Monitor Out / R");
- stereo_in_l->identifier.owner_type =
- PORT_OWNER_TYPE_BACKEND;
- stereo_in_r->identifier.owner_type =
+ monitor_out_l->identifier.owner_type =
PORT_OWNER_TYPE_BACKEND;
- stereo_out_l->identifier.owner_type =
- PORT_OWNER_TYPE_BACKEND;
- stereo_out_r->identifier.owner_type =
+ monitor_out_r->identifier.owner_type =
PORT_OWNER_TYPE_BACKEND;
- self->stereo_out =
- stereo_ports_new_from_existing (
- stereo_out_l, stereo_out_r);
- self->stereo_in =
+ self->monitor_out =
stereo_ports_new_from_existing (
- stereo_in_l, stereo_in_r);
+ monitor_out_l, monitor_out_r);
pthread_t thread_id;
pthread_create(
@@ -550,32 +554,10 @@ alsa_midi_setup (
}
else
{
- self->midi_in =
- port_new_with_type (
- TYPE_EVENT,
- FLOW_INPUT,
- "ALSA MIDI In");
- self->midi_in->identifier.owner_type =
- PORT_OWNER_TYPE_BACKEND;
- self->midi_out =
- port_new_with_type (
- TYPE_EVENT,
- FLOW_OUTPUT,
- "ALSA MIDI Out");
- self->midi_out->identifier.owner_type =
- PORT_OWNER_TYPE_BACKEND;
}
- /* init queue */
- self->midi_in->midi_events =
- midi_events_new (
- self->midi_in);
- self->midi_out->midi_events =
- midi_events_new (
- self->midi_out);
-
pthread_t thread_id;
- pthread_create(
+ pthread_create (
&thread_id, NULL,
&midi_thread, self);
diff --git a/src/audio/engine_dummy.c b/src/audio/engine_dummy.c
index 722a383..ae77e50 100644
--- a/src/audio/engine_dummy.c
+++ b/src/audio/engine_dummy.c
@@ -59,49 +59,36 @@ engine_dummy_setup (
self->sample_rate);
/* create ports */
- Port * stereo_out_l, * stereo_out_r,
- * stereo_in_l, * stereo_in_r;
+ Port * monitor_out_l, * monitor_out_r;
if (loading)
{
}
else
{
- stereo_out_l =
+ monitor_out_l =
port_new_with_data (
INTERNAL_PA_PORT,
TYPE_AUDIO,
FLOW_OUTPUT,
- "Dummy Stereo Out / L",
+ "Dummy Monitor L",
NULL);
- stereo_out_r =
+ monitor_out_r =
port_new_with_data (
INTERNAL_PA_PORT,
TYPE_AUDIO,
FLOW_OUTPUT,
- "Dummy Stereo Out / R",
- NULL);
- stereo_in_l =
- port_new_with_data (
- INTERNAL_PA_PORT,
- TYPE_AUDIO,
- FLOW_INPUT,
- "Dummy Stereo In / L",
- NULL);
- stereo_in_r =
- port_new_with_data (
- INTERNAL_PA_PORT,
- TYPE_AUDIO,
- FLOW_INPUT,
- "Dummy Stereo In / R",
+ "Dummy Monitor R",
NULL);
- self->stereo_in =
- stereo_ports_new_from_existing (stereo_in_l,
- stereo_in_r);
- self->stereo_out =
- stereo_ports_new_from_existing (stereo_out_l,
- stereo_out_r);
+ monitor_out_l->identifier.owner_type =
+ PORT_OWNER_TYPE_BACKEND;
+ monitor_out_r->identifier.owner_type =
+ PORT_OWNER_TYPE_BACKEND;
+
+ self->monitor_out =
+ stereo_ports_new_from_existing (
+ monitor_out_l, monitor_out_r);
}
g_thread_new ("process_cb",
@@ -124,12 +111,12 @@ engine_dummy_midi_setup (
}
else
{
- self->midi_in =
- port_new_with_type (
- TYPE_EVENT,
- FLOW_INPUT,
- "Dummy MIDI In");
- self->midi_in->identifier.owner_type =
- PORT_OWNER_TYPE_BACKEND;
+ /*self->midi_in =*/
+ /*port_new_with_type (*/
+ /*TYPE_EVENT,*/
+ /*FLOW_INPUT,*/
+ /*"Dummy MIDI In");*/
+ /*self->midi_in->identifier.owner_type =*/
+ /*PORT_OWNER_TYPE_BACKEND;*/
}
}
diff --git a/src/audio/engine_jack.c b/src/audio/engine_jack.c
index 8a0ec72..9e8fe38 100644
--- a/src/audio/engine_jack.c
+++ b/src/audio/engine_jack.c
@@ -24,6 +24,7 @@
#include "audio/channel.h"
#include "audio/engine.h"
#include "audio/engine_jack.h"
+#include "audio/ext_port.h"
#include "audio/midi.h"
#include "audio/mixer.h"
#include "audio/port.h"
@@ -40,16 +41,114 @@
#include <jack/statistics.h>
+/**
+ * Adds a port to the array if it doesn't already
+ * exist.
+ */
+static void
+add_port_if_not_exists (
+ Port ** ports,
+ int * num_ports,
+ jack_port_t * jport)
+{
+ int found = 0;
+ Port * port = NULL;
+ const char * jport_name =
+ jack_port_short_name (jport);
+ for (int i = 0; i < * num_ports; i++)
+ {
+ port = ports[i];
+
+ if (g_strstr_len (
+ port->identifier.label,
+ strlen (port->identifier.label),
+ jport_name))
+ {
+ found = 1;
+ }
+ }
+
+ if (found)
+ return;
+
+ PortType type;
+ PortFlow flow;
+
+ const char * jtype =
+ jack_port_type (jport);
+ if (g_strcmp0 (
+ jtype, JACK_DEFAULT_AUDIO_TYPE))
+ type = TYPE_EVENT;
+ else if (g_strcmp0 (
+ jtype, JACK_DEFAULT_MIDI_TYPE))
+ type = TYPE_AUDIO;
+ else
+ return;
+
+ int jflags = jack_port_flags (jport);
+ if (jflags & JackPortIsInput)
+ flow = FLOW_INPUT;
+ else if (jflags & JackPortIsOutput)
+ flow = FLOW_OUTPUT;
+ else
+ return;
+
+ port = port_new_with_data (
+ INTERNAL_JACK_PORT,
+ type,
+ flow,
+ jport_name,
+ (void *) jport);
+
+ ports[(*num_ports)++] = port;
+}
+
+/**
+ * Refreshes the list of external ports.
+ */
void
-engine_jack_autoconnect_midi_controllers (
+engine_jack_rescan_ports (
AudioEngine * self)
{
- /* get all output ports */
+ /* get all input ports */
const char ** ports =
jack_get_ports (
self->client,
NULL, NULL,
JackPortIsPhysical |
+ JackPortIsInput);
+
+ int i = 0;
+ char * pname;
+ jack_port_t * jport;
+ while ((pname = (char *) ports[i]) != NULL)
+ {
+ jport =
+ jack_port_by_name (
+ self->client,
+ pname);
+
+ /*add_port_if_not_exists (*/
+ /*self->physical_ins,*/
+ /*&self->num_physical_ins,*/
+ /*jport);*/
+
+ i++;
+ }
+
+ /* TODO clear unconnected remembered ports */
+}
+
+void
+engine_jack_autoconnect_midi_controllers (
+ AudioEngine * self)
+{
+ /* get all output MIDI ports */
+ const char ** ports =
+ jack_get_ports (
+ self->client,
+ NULL, JACK_DEFAULT_MIDI_TYPE,
+ JackPortIsPhysical |
JackPortIsOutput);
if(!ports) return;
@@ -78,16 +177,16 @@ engine_jack_autoconnect_midi_controllers (
if (g_str_match_string (
device, pname, 1))
{
- if (jack_connect (
- self->client,
- pname,
- jack_port_name (
- JACK_PORT_T (
- self->midi_in->data))))
- g_warning (
- "Failed connecting %s to %s",
- pname,
- self->midi_in->identifier.label);
+ /*if (jack_connect (*/
+ /*self->client,*/
+ /*pname,*/
+ /*jack_port_name (*/
+ /*JACK_PORT_T (*/
+ /*self->midi_in->data))))*/
+ /*g_warning (*/
+ /*"Failed connecting %s to %s",*/
+ /*pname,*/
+ /*self->midi_in->identifier.label);*/
break;
@@ -141,29 +240,14 @@ buffer_size_cb (uint32_t nframes,
*/
void
engine_jack_clear_output_buffers (
- AudioEngine * self)
+ AudioEngine * self,
+ int nframes)
{
- int nframes = AUDIO_ENGINE->nframes;
- float * out_l =
- (float *)
- jack_port_get_buffer (
- JACK_PORT_T (AUDIO_ENGINE->stereo_out->l->data),
- nframes);
- float * out_r =
- (float *)
- jack_port_get_buffer (
- JACK_PORT_T (AUDIO_ENGINE->stereo_out->r->data),
- nframes);
-
- for (int i = 0; i < nframes; i++)
- {
- out_l[i] = 0;
- out_r[i] = 0;
- }
-
- /* avoid unused warnings */
- (void) out_l;
- (void) out_r;
+ /*for (int i = 0; i < self->num_hw_stereo_outs; i++)*/
+ /*{*/
+ /*ext_port_clear_buffer (*/
+ /*self->hw_stereo_outs[i], nframes);*/
+ /*}*/
}
/**
@@ -213,6 +297,8 @@ engine_jack_prepare_process (
TRANSPORT, pos.beat_type);
}
}
+
+ /* clear output */
}
/**
@@ -308,58 +394,58 @@ jack_midi_setup (
if (loading)
{
- self->midi_in->data =
- (void *) jack_port_register (
- self->client, "MIDI_in",
- JACK_DEFAULT_MIDI_TYPE,
- JackPortIsInput, 0);
- self->midi_out->data =
- (void *) jack_port_register (
- self->client, "MIDI_out",
- JACK_DEFAULT_MIDI_TYPE,
- JackPortIsOutput, 0);
+ /*self->midi_in->data =*/
+ /*(void *) jack_port_register (*/
+ /*self->client, "MIDI_in",*/
+ /*JACK_DEFAULT_MIDI_TYPE,*/
+ /*JackPortIsInput, 0);*/
+ /*self->midi_out->data =*/
+ /*(void *) jack_port_register (*/
+ /*self->client, "MIDI_out",*/
+ /*JACK_DEFAULT_MIDI_TYPE,*/
+ /*JackPortIsOutput, 0);*/
}
else
{
- self->midi_in =
- port_new_with_data (
- INTERNAL_JACK_PORT,
- TYPE_EVENT,
- FLOW_INPUT,
- "JACK MIDI In",
- (void *) jack_port_register (
- self->client, "MIDI_in",
- JACK_DEFAULT_MIDI_TYPE,
- JackPortIsInput, 0));
- self->midi_in->identifier.owner_type =
- PORT_OWNER_TYPE_BACKEND;
- self->midi_out =
- port_new_with_data (
- INTERNAL_JACK_PORT,
- TYPE_EVENT,
- FLOW_OUTPUT,
- "JACK MIDI Out",
- (void *) jack_port_register (
- self->client, "MIDI_out",
- JACK_DEFAULT_MIDI_TYPE,
- JackPortIsOutput, 0));
- self->midi_out->identifier.owner_type =
- PORT_OWNER_TYPE_BACKEND;
+ /*self->midi_in =*/
+ /*port_new_with_data (*/
+ /*INTERNAL_JACK_PORT,*/
+ /*TYPE_EVENT,*/
+ /*FLOW_INPUT,*/
+ /*"JACK MIDI In",*/
+ /*(void *) jack_port_register (*/
+ /*self->client, "MIDI_in",*/
+ /*JACK_DEFAULT_MIDI_TYPE,*/
+ /*JackPortIsInput, 0));*/
+ /*self->midi_in->identifier.owner_type =*/
+ /*PORT_OWNER_TYPE_BACKEND;*/
+ /*self->midi_out =*/
+ /*port_new_with_data (*/
+ /*INTERNAL_JACK_PORT,*/
+ /*TYPE_EVENT,*/
+ /*FLOW_OUTPUT,*/
+ /*"JACK MIDI Out",*/
+ /*(void *) jack_port_register (*/
+ /*self->client, "MIDI_out",*/
+ /*JACK_DEFAULT_MIDI_TYPE,*/
+ /*JackPortIsOutput, 0));*/
+ /*self->midi_out->identifier.owner_type =*/
+ /*PORT_OWNER_TYPE_BACKEND;*/
}
/* init queue */
- self->midi_in->midi_events =
- midi_events_new (
- self->midi_in);
- self->midi_out->midi_events =
- midi_events_new (
- self->midi_out);
-
- if (!self->midi_in->data ||
- !self->midi_out->data)
- {
- g_warning ("no more JACK ports available");
- }
+ /*self->midi_in->midi_events =*/
+ /*midi_events_new (*/
+ /*self->midi_in);*/
+ /*self->midi_out->midi_events =*/
+ /*midi_events_new (*/
+ /*self->midi_out);*/
+
+ /*if (!self->midi_in->data ||*/
+ /*!self->midi_out->data)*/
+ /*{*/
+ /*g_warning ("no more JACK ports available");*/
+ /*}*/
/* autoconnect MIDI controllers */
engine_jack_autoconnect_midi_controllers (
@@ -505,104 +591,71 @@ jack_setup (AudioEngine * self,
#endif
/* create ports */
- Port * stereo_out_l, * stereo_out_r,
- * stereo_in_l, * stereo_in_r;
+ Port * monitor_out_l, * monitor_out_r;
+
+ const char * monitor_out_l_str =
+ "Monitor out L";
+ const char * monitor_out_r_str =
+ "Monitor out R";
if (loading)
{
- self->stereo_out->l->data =
+ self->monitor_out->l->data =
(void *) jack_port_register (
- self->client, "Stereo_out_L",
+ self->client, monitor_out_l_str,
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
- self->stereo_out->r->data =
+ self->monitor_out->r->data =
(void *) jack_port_register (
- self->client, "Stereo_out_R",
+ self->client, monitor_out_r_str,
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
- self->stereo_in->l->data =
- (void *) jack_port_register (
- self->client, "Stereo_in_L",
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsInput, 0);
- self->stereo_in->r->data =
- (void *) jack_port_register (
- self->client, "Stereo_in_R",
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsInput, 0);
}
else
{
- stereo_out_l = port_new_with_data (
+ monitor_out_l = port_new_with_data (
INTERNAL_JACK_PORT,
TYPE_AUDIO,
FLOW_OUTPUT,
- "JACK Stereo Out / L",
+ monitor_out_l_str,
(void *) jack_port_register (
- self->client, "Stereo_out_L",
+ self->client, monitor_out_l_str,
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0));
- stereo_out_l->identifier.flags |=
- PORT_FLAG_STEREO_L;
- stereo_out_r = port_new_with_data (
+ monitor_out_r = port_new_with_data (
INTERNAL_JACK_PORT,
TYPE_AUDIO,
FLOW_OUTPUT,
- "JACK Stereo Out / R",
+ monitor_out_r_str,
(void *) jack_port_register (
- self->client, "Stereo_out_R",
+ self->client, monitor_out_r_str,
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0));
- stereo_out_r->identifier.flags |=
- PORT_FLAG_STEREO_R;
- stereo_in_l = port_new_with_data (
- INTERNAL_JACK_PORT,
- TYPE_AUDIO,
- FLOW_INPUT,
- "JACK Stereo In / L",
- (void *) jack_port_register (
- self->client, "Stereo_in_L",
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsInput, 0));
- stereo_in_l->identifier.flags |=
- PORT_FLAG_STEREO_L;
- stereo_in_r = port_new_with_data (
- INTERNAL_JACK_PORT,
- TYPE_AUDIO,
- FLOW_INPUT,
- "JACK Stereo In / R",
- (void *) jack_port_register (
- self->client, "Stereo_in_R",
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsInput, 0));
- stereo_in_r->identifier.flags |=
- PORT_FLAG_STEREO_R;
- stereo_in_l->identifier.owner_type =
- PORT_OWNER_TYPE_BACKEND;
- stereo_in_r->identifier.owner_type =
- PORT_OWNER_TYPE_BACKEND;
- stereo_out_l->identifier.owner_type =
+ monitor_out_l->identifier.owner_type =
PORT_OWNER_TYPE_BACKEND;
- stereo_out_r->identifier.owner_type =
+ monitor_out_r->identifier.owner_type =
PORT_OWNER_TYPE_BACKEND;
- self->stereo_in =
+ self->monitor_out =
stereo_ports_new_from_existing (
- stereo_in_l, stereo_in_r);
- self->stereo_out =
- stereo_ports_new_from_existing (
- stereo_out_l, stereo_out_r);
+ monitor_out_l, monitor_out_r);
}
- if (!self->stereo_in->l->data ||
- !self->stereo_in->r->data ||
- !self->stereo_out->l->data ||
- !self->stereo_out->r->data)
+ if (!self->monitor_out->l->data ||
+ !self->monitor_out->r->data)
{
g_error ("no more JACK ports available");
}
+ /*engine_jack_rescan_ports (self);*/
+
+ /* get all input physical ports */
+ ext_ports_get (
+ TYPE_AUDIO,
+ FLOW_INPUT,
+ 1, self->hw_stereo_outs,
+ &self->num_hw_stereo_outs);
g_message ("JACK set up");
return 0;
@@ -689,6 +742,34 @@ jack_tear_down ()
1);
}
+/**
+ * Fills the external out bufs.
+ */
+void
+engine_jack_fill_out_bufs (
+ AudioEngine * self,
+ int nframes)
+{
+ /*g_message ("filling out bufs");*/
+ /*g_message ("%p", self->hw_stereo_outs[0]);*/
+ /*float * l_buf =*/
+ /*ext_port_get_buffer (*/
+ /*self->hw_stereo_outs[0], nframes);*/
+ /*float * r_buf =*/
+ /*ext_port_get_buffer (*/
+ /*self->hw_stereo_outs[1], nframes);*/
+
+ /*for (int i = 0; i < nframes; i++)*/
+ /*{*/
+ /*if (i == 50)*/
+ /*g_message ("before lbuf %f", l_buf[i]);*/
+ /*l_buf[i] = self->monitor_out->l->buf[i];*/
+ /*if (i == 50)*/
+ /*g_message ("after lbuf %f", l_buf[i]);*/
+ /*r_buf[i] = self->monitor_out->r->buf[i];*/
+ /*}*/
+}
+
int
engine_jack_activate (
AudioEngine * self)
@@ -710,9 +791,12 @@ engine_jack_activate (
* it.
*/
+ /* FIXME this just connects to the first ports
+ * it finds. add a menu in the welcome screen to
+ * set up default output */
const char **ports =
jack_get_ports (
- self->client, NULL, NULL,
+ self->client, NULL, JACK_DEFAULT_AUDIO_TYPE,
JackPortIsPhysical|JackPortIsInput);
if (ports == NULL) {
g_error ("no physical playback ports\n");
@@ -723,14 +807,14 @@ engine_jack_activate (
self->client,
jack_port_name (
JACK_PORT_T (
- self->stereo_out->l->data)),
+ self->monitor_out->l->data)),
ports[0]))
g_error ("cannot connect output ports\n");
if (jack_connect (
self->client,
jack_port_name (
- JACK_PORT_T (self->stereo_out->r->data)),
+ JACK_PORT_T (self->monitor_out->r->data)),
ports[1]))
g_error ("cannot connect output ports\n");
diff --git a/src/audio/engine_pa.c b/src/audio/engine_pa.c
index 8c1e4e3..a83c1bb 100644
--- a/src/audio/engine_pa.c
+++ b/src/audio/engine_pa.c
@@ -63,49 +63,32 @@ pa_setup (
self->sample_rate);
/* create ports */
- Port * stereo_out_l, * stereo_out_r,
- * stereo_in_l, * stereo_in_r;
+ Port * monitor_out_l, * monitor_out_r;
if (loading)
{
}
else
{
- stereo_out_l =
+ monitor_out_l =
port_new_with_data (
INTERNAL_PA_PORT,
TYPE_AUDIO,
FLOW_OUTPUT,
"PortAudio Stereo Out / L",
NULL);
- stereo_out_r =
+ monitor_out_r =
port_new_with_data (
INTERNAL_PA_PORT,
TYPE_AUDIO,
FLOW_OUTPUT,
"PortAudio Stereo Out / R",
NULL);
- stereo_in_l =
- port_new_with_data (
- INTERNAL_PA_PORT,
- TYPE_AUDIO,
- FLOW_INPUT,
- "PortAudio Stereo In / L",
- NULL);
- stereo_in_r =
- port_new_with_data (
- INTERNAL_PA_PORT,
- TYPE_AUDIO,
- FLOW_INPUT,
- "PortAudio Stereo In / R",
- NULL);
- self->stereo_in =
- stereo_ports_new_from_existing (stereo_in_l,
- stereo_in_r);
- self->stereo_out =
- stereo_ports_new_from_existing (stereo_out_l,
- stereo_out_r);
+ self->monitor_out =
+ stereo_ports_new_from_existing (
+ monitor_out_l,
+ monitor_out_r);
self->pa_out_buf =
calloc (self->block_length * 2,
@@ -128,20 +111,20 @@ pa_setup (
}
void
-engine_pa_fill_stereo_out_buffs (
- AudioEngine * engine)
+engine_pa_fill_out_bufs (
+ AudioEngine * engine,
+ int nframes)
{
- int nframes = engine->nframes;
for (int i = 0; i < nframes; i++)
{
engine->pa_out_buf[i * 2] =
- P_MASTER_TRACK->channel->
- stereo_out->l->buf[i];
+ AUDIO_ENGINE->
+ monitor_out->l->buf[i];
g_message ("%f",
engine->pa_out_buf[i]);
engine->pa_out_buf[i * 2 + 1] =
- P_MASTER_TRACK->channel->
- stereo_out->r->buf[i];
+ AUDIO_ENGINE->
+ monitor_out->r->buf[i];
}
}
diff --git a/src/audio/ext_port.c b/src/audio/ext_port.c
new file mode 100644
index 0000000..0e29f1e
--- /dev/null
+++ b/src/audio/ext_port.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2019 Alexandros Theodotou <alex at zrythm dot org>
+ *
+ * This file is part of Zrythm
+ *
+ * Zrythm is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Zrythm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "audio/engine.h"
+#include "audio/ext_port.h"
+#include "project.h"
+
+#ifdef HAVE_JACK
+#include <jack/jack.h>
+#endif
+
+/**
+ * Inits the ExtPort after loading a project.
+ */
+void
+ext_port_init_loaded (
+ ExtPort * ext_port)
+{
+ /* TODO */
+}
+
+/**
+ * Returns the buffer of the external port.
+ */
+float *
+ext_port_get_buffer (
+ ExtPort * self,
+ int nframes)
+{
+ switch (self->type)
+ {
+ case EXT_PORT_TYPE_JACK:
+ return
+ (float *)
+ jack_port_get_buffer (
+ self->jport,
+ nframes);
+ break;
+ case EXT_PORT_TYPE_ALSA:
+ default:
+ g_return_val_if_reached (NULL);
+ break;
+ }
+}
+
+/**
+ * Clears the buffer of the external port.
+ */
+void
+ext_port_clear_buffer (
+ ExtPort * ext_port,
+ int nframes)
+{
+ float * buf =
+ ext_port_get_buffer (ext_port, nframes);
+ g_message ("clearing buffer of %p", ext_port);
+
+ memset (
+ buf, 0,
+ nframes * sizeof (float));
+}
+
+/**
+ * Exposes the given Port if not exposed and makes
+ * the connection from the Port to the ExtPort (eg in
+ * JACK) or backwards.
+ *
+ * @param src 1 if the ext_port is the source, 0 if it
+ * is the destination.
+ */
+void
+ext_port_connect (
+ ExtPort * ext_port,
+ Port * port,
+ int src)
+{
+ /* TODO */
+}
+
+/**
+ * Disconnects the Port from the ExtPort.
+ *
+ * @param src 1 if the ext_port is the source, 0 if it
+ * is the destination.
+ */
+void
+ext_port_disconnect (
+ ExtPort * ext_port,
+ Port * port,
+ int src)
+{
+ /* TODO */
+}
+
+/**
+ * Collects external ports of the given type.
+ *
+ * @param hw Hardware or not.
+ * @param ports An array of ExtPort pointers to fill
+ * in. The array should be preallocated.
+ * @param size Size of the array to fill in.
+ */
+void
+ext_ports_get (
+ PortType type,
+ PortFlow flow,
+ int hw,
+ ExtPort ** arr,
+ int * size)
+{
+ switch (AUDIO_ENGINE->audio_backend)
+ {
+ case AUDIO_BACKEND_JACK:
+ {
+#ifdef HAVE_JACK
+ int flags = 0;
+ if (hw)
+ flags |= JackPortIsPhysical;
+ if (flow == FLOW_INPUT)
+ flags |= JackPortIsInput;
+ else if (flow == FLOW_OUTPUT)
+ flags |= JackPortIsOutput;
+ char * jtype = NULL;
+ if (type == TYPE_AUDIO)
+ jtype = JACK_DEFAULT_AUDIO_TYPE;
+ else if (type == TYPE_EVENT)
+ jtype = JACK_DEFAULT_MIDI_TYPE;
+
+ const char ** ports =
+ jack_get_ports (
+ AUDIO_ENGINE->client,
+ NULL, jtype, flags);
+
+ int i = 0;
+ char * pname;
+ jack_port_t * jport;
+ while ((pname = (char *) ports[i]) != NULL)
+ {
+ jport =
+ jack_port_by_name (
+ AUDIO_ENGINE->client,
+ pname);
+
+ arr[i] =
+ ext_port_from_jack_port (jport);
+
+ i++;
+ }
+
+ *size = i;
+#endif
+ }
+ break;
+ case AUDIO_BACKEND_ALSA:
+ break;
+ default:
+ break;
+ }
+}
+
+#ifdef HAVE_JACK
+
+/**
+ * Creates an ExtPort from a JACK port.
+ */
+ExtPort *
+ext_port_from_jack_port (
+ jack_port_t * jport)
+{
+ ExtPort * self =
+ calloc (1, sizeof (ExtPort));
+
+ self->jport = jport;
+ self->full_name =
+ g_strdup (jack_port_name (jport));
+ self->short_name =
+ g_strdup (jack_port_short_name (jport));
+ self->type = EXT_PORT_TYPE_JACK;
+
+ return self;
+}
+
+#endif
+
+/**
+ * Frees an array of ExtPort pointers.
+ */
+void
+ext_ports_free (
+ ExtPort ** ext_port,
+ int size)
+{
+ /* TODO */
+}
+
+/**
+ * Frees the ext_port.
+ */
+void
+ext_port_free (
+ ExtPort * ext_port)
+{
+ /* TODO */
+}
diff --git a/src/audio/fader.c b/src/audio/fader.c
index 2c3b08b..9e69a0a 100644
--- a/src/audio/fader.c
+++ b/src/audio/fader.c
@@ -60,13 +60,20 @@ fader_init (
/* stereo in */
self->stereo_in =
stereo_ports_new_generic (
- 1, _("Fader in"), PORT_OWNER_TYPE_FADER,
+ 1, _("Fader in"),
+ ch ?
+ PORT_OWNER_TYPE_FADER :
+ PORT_OWNER_TYPE_MONITOR_FADER,
self);
/* stereo out */
self->stereo_out =
stereo_ports_new_generic (
- 0, _("Fader out"), PORT_OWNER_TYPE_FADER,
+ 0, _("Fader out"),
+ /* FIXME just create another type */
+ ch ?
+ PORT_OWNER_TYPE_FADER :
+ PORT_OWNER_TYPE_MONITOR_FADER,
self);
}
diff --git a/src/audio/meson.build b/src/audio/meson.build
index bb43823..bdbc1d4 100644
--- a/src/audio/meson.build
+++ b/src/audio/meson.build
@@ -38,6 +38,7 @@ audio_srcs = [
'engine_jack.c',
'engine_pa.c',
'exporter.c',
+ 'ext_port.c',
'fader.c',
'audio_group_track.c',
'instrument_track.c',
diff --git a/src/audio/port.c b/src/audio/port.c
index f8b7063..a127686 100644
--- a/src/audio/port.c
+++ b/src/audio/port.c
@@ -125,26 +125,22 @@ port_find_from_identifier (
return
AUDIO_ENGINE->
midi_editor_manual_press;
- else
- return AUDIO_ENGINE->midi_in;
}
break;
case TYPE_AUDIO:
if (id->flow == FLOW_OUTPUT)
{
if (id->flags & PORT_FLAG_STEREO_L)
- return AUDIO_ENGINE->stereo_out->l;
+ return
+ AUDIO_ENGINE->monitor_out->l;
else if (id->flags &
PORT_FLAG_STEREO_R)
- return AUDIO_ENGINE->stereo_out->r;
+ return
+ AUDIO_ENGINE->monitor_out->r;
}
else if (id->flow == FLOW_INPUT)
{
- if (id->flags & PORT_FLAG_STEREO_L)
- return AUDIO_ENGINE->stereo_in->l;
- else if (id->flags &
- PORT_FLAG_STEREO_R)
- return AUDIO_ENGINE->stereo_in->r;
+ /* none */
}
break;
default:
@@ -252,7 +248,7 @@ port_find_from_identifier (
else if (id->flow == FLOW_INPUT)
{
if (id->flags & PORT_FLAG_STEREO_L)
- return ch->prefader.stereo_in->r;
+ return ch->prefader.stereo_in->l;
else if (id->flags &
PORT_FLAG_STEREO_R)
return ch->prefader.stereo_in->r;
@@ -264,6 +260,31 @@ port_find_from_identifier (
else if (id->flags &
PORT_FLAG_STEREO_R)
return SAMPLE_PROCESSOR->stereo_out->r;
+ case PORT_OWNER_TYPE_MONITOR_FADER:
+ if (id->flow == FLOW_OUTPUT)
+ {
+ if (id->flags & PORT_FLAG_STEREO_L)
+ return
+ AUDIO_ENGINE->monitor_fader.
+ stereo_out->l;
+ else if (id->flags &
+ PORT_FLAG_STEREO_R)
+ return
+ AUDIO_ENGINE->monitor_fader.
+ stereo_out->r;
+ }
+ else if (id->flow == FLOW_INPUT)
+ {
+ if (id->flags & PORT_FLAG_STEREO_L)
+ return
+ AUDIO_ENGINE->monitor_fader.
+ stereo_in->l;
+ else if (id->flags &
+ PORT_FLAG_STEREO_R)
+ return
+ AUDIO_ENGINE->monitor_fader.
+ stereo_in->r;
+ }
}
g_return_val_if_reached (NULL);
@@ -282,7 +303,8 @@ stereo_ports_init_loaded (StereoPorts * sp)
* Sets id and updates appropriate counters.
*/
Port *
-port_new (char * label)
+port_new (
+ const char * label)
{
Port * port = calloc (1, sizeof (Port));
@@ -305,18 +327,25 @@ port_new (char * label)
* Creates port.
*/
Port *
-port_new_with_type (PortType type,
- PortFlow flow,
- char * label)
+port_new_with_type (
+ PortType type,
+ PortFlow flow,
+ const char * label)
{
- Port * port = port_new (label);
+ Port * self = port_new (label);
- port->identifier.type = type;
- if (port->identifier.type == TYPE_EVENT)
- port->midi_events = midi_events_new (port);
- port->identifier.flow = flow;
+ self->identifier.type = type;
+ if (self->identifier.type == TYPE_EVENT)
+ self->midi_events = midi_events_new (self);
+ self->identifier.flow = flow;
- return port;
+ if (type == TYPE_EVENT)
+ {
+ self->midi_events =
+ midi_events_new (self);
+ }
+
+ return self;
}
/**
@@ -329,12 +358,34 @@ stereo_ports_new_from_existing (
StereoPorts * sp =
calloc (1, sizeof (StereoPorts));
sp->l = l;
+ l->identifier.flags |= PORT_FLAG_STEREO_L;
+ r->identifier.flags |= PORT_FLAG_STEREO_R;
sp->r = r;
return sp;
}
/**
+ * Connects the internal ports using
+ * port_connect().
+ *
+ * @param locked Lock the connection.
+ */
+void
+stereo_ports_connect (
+ StereoPorts * src,
+ StereoPorts * dest,
+ int locked)
+{
+ port_connect (
+ src->l,
+ dest->l, locked);
+ port_connect (
+ src->r,
+ dest->r, locked);
+}
+
+/**
* Gathers all ports in the project and puts them
* in the given array and size.
*/
@@ -350,12 +401,14 @@ port_get_all (
ports, (*size), \
port)
- _ADD (AUDIO_ENGINE->stereo_in->l);
- _ADD (AUDIO_ENGINE->stereo_in->r);
- _ADD (AUDIO_ENGINE->stereo_out->l);
- _ADD (AUDIO_ENGINE->stereo_out->r);
- _ADD (AUDIO_ENGINE->midi_in);
- _ADD (AUDIO_ENGINE->midi_out);
+ /* add fader ports */
+ _ADD (AUDIO_ENGINE->monitor_fader.stereo_in->l);
+ _ADD (AUDIO_ENGINE->monitor_fader.stereo_in->r);
+ _ADD (AUDIO_ENGINE->monitor_fader.stereo_out->l);
+ _ADD (AUDIO_ENGINE->monitor_fader.stereo_out->r);
+
+ _ADD (AUDIO_ENGINE->monitor_out->l);
+ _ADD (AUDIO_ENGINE->monitor_out->r);
_ADD (AUDIO_ENGINE->midi_editor_manual_press);
_ADD (SAMPLE_PROCESSOR->stereo_out->l);
_ADD (SAMPLE_PROCESSOR->stereo_out->r);
@@ -379,13 +432,15 @@ port_get_all (
* Creates port and adds given data to it.
*/
Port *
-port_new_with_data (PortInternalType internal_type, ///< the internal data format
- PortType type,
- PortFlow flow,
- char * label,
- void * data) ///< the data
+port_new_with_data (
+ PortInternalType internal_type,
+ PortType type,
+ PortFlow flow,
+ const char * label,
+ void * data)
{
- Port * port = port_new_with_type (type, flow, label);
+ Port * port =
+ port_new_with_type (type, flow, label);
/** TODO semaphore **/
port->data = data;
@@ -759,6 +814,11 @@ stereo_ports_new_generic (
port_set_owner_sample_processor (
ports->r, (SampleProcessor *) owner);
break;
+ case PORT_OWNER_TYPE_MONITOR_FADER:
+ ports->l->identifier.owner_type =
+ PORT_OWNER_TYPE_MONITOR_FADER;
+ ports->r->identifier.owner_type =
+ PORT_OWNER_TYPE_MONITOR_FADER;
default:
break;
}
@@ -769,6 +829,198 @@ stereo_ports_new_generic (
return ports;
}
+/**
+ * First sets port buf to 0, then sums the given
+ * port signal from its inputs.
+ *
+ * @param start_frame The start frame offset from
+ * 0 in this cycle.
+ * @param nframes The number of frames to process.
+ * @param noroll Clear the port buffer in this
+ * range.
+ */
+void
+port_sum_signal_from_inputs (
+ Port * port,
+ const int start_frame,
+ const int nframes,
+ const int noroll)
+{
+ Port * src_port;
+ int k, l;
+
+ g_warn_if_fail (
+ start_frame + nframes <=
+ AUDIO_ENGINE->nframes);
+
+ switch (port->identifier.type)
+ {
+ case TYPE_EVENT:
+ if (noroll)
+ break;
+
+ port_sum_data_from_jack (
+ port, start_frame, nframes);
+
+ for (k = 0; k < port->num_srcs; k++)
+ {
+ src_port = port->srcs[k];
+ g_warn_if_fail (
+ src_port->identifier.type ==
+ TYPE_EVENT);
+ midi_events_append (
+ src_port->midi_events,
+ port->midi_events, start_frame,
+ nframes, 0);
+ }
+
+ port_send_data_to_jack (
+ port, start_frame, nframes);
+
+ /* send UI notification */
+ if (port->midi_events->num_events > 0)
+ {
+ g_message ("port %s has %d events",
+ port->identifier.label,
+ port->midi_events->num_events);
+ /*if (port == AUDIO_ENGINE->midi_in)*/
+ /*{*/
+ /*AUDIO_ENGINE->trigger_midi_activity = 1;*/
+ /*}*/
+ if (port->identifier.owner_type ==
+ PORT_OWNER_TYPE_TRACK)
+ {
+ port->track->trigger_midi_activity = 1;
+ }
+ }
+ break;
+ case TYPE_AUDIO:
+ if (noroll)
+ {
+ for (l = start_frame; l < nframes; l++)
+ {
+ port->buf[l] = 0;
+ }
+ break;
+ }
+
+ port_sum_data_from_jack (
+ port, start_frame, nframes);
+
+ for (k = 0; k < port->num_srcs; k++)
+ {
+ src_port = port->srcs[k];
+
+ /* sum the signals */
+ /*g_message ("port %s start frame %ld nframes %d",*/
+ /*port->identifier.label,*/
+ /*start_frame, nframes);*/
+ for (l = start_frame; l < nframes; l++)
+ {
+ port->buf[l] += src_port->buf[l];
+ }
+ }
+
+ port_send_data_to_jack (
+ port, start_frame, nframes);
+ break;
+ case TYPE_CONTROL:
+ {
+ float maxf, minf, depth_range, val_to_use;
+ /* whether this is the first CV processed
+ * on this control port */
+ int first_cv = 1;
+ for (k = 0; k < port->num_srcs; k++)
+ {
+ src_port = port->srcs[k];
+
+ if (src_port->identifier.type ==
+ TYPE_CV)
+ {
+ maxf =
+ port->lv2_port->lv2_control->maxf;
+ minf =
+ port->lv2_port->lv2_control->minf;
+ /*float deff =*/
+ /*port->lv2_port->lv2_control->deff;*/
+ /*port->lv2_port->control =*/
+ /*deff + (maxf - deff) **/
+ /*src_port->buf[0];*/
+ depth_range =
+ (maxf - minf) / 2.f;
+
+ /* figure out whether to use base
+ * value or the current value */
+ if (first_cv)
+ {
+ val_to_use = port->base_value;
+ first_cv = 0;
+ }
+ else
+ val_to_use =
+ port->lv2_port->control;
+
+ /* TODO replace 1.f with modulator
+ * depth */
+ port->lv2_port->control =
+ CLAMP (
+ val_to_use +
+ depth_range * src_port->buf[0] *
+ src_port->multipliers[
+ port_get_dest_index (
+ src_port, port)],
+ minf, maxf);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Sets whether to expose the port to the backend
+ * and exposes it or removes it.
+ *
+ * It checks what the backend is using the engine's
+ * audio backend or midi backend settings.
+ */
+void
+port_set_expose_to_backend (
+ Port * self,
+ int expose)
+{
+ if (self->identifier.type == TYPE_AUDIO)
+ {
+ switch (AUDIO_ENGINE->audio_backend)
+ {
+ case AUDIO_BACKEND_JACK:
+ port_set_expose_to_jack (self, expose);
+ break;
+ default:
+ break;
+ }
+ }
+ else if (self->identifier.type == TYPE_EVENT)
+ {
+ switch (AUDIO_ENGINE->midi_backend)
+ {
+ case MIDI_BACKEND_JACK:
+ port_set_expose_to_jack (self, expose);
+ break;
+ case MIDI_BACKEND_ALSA:
+ port_set_expose_to_alsa (self, expose);
+ break;
+ default:break;
+ }
+ }
+ else
+ g_return_if_reached ();
+}
+
+#ifdef HAVE_JACK
+
void
port_receive_midi_events_from_jack (
Port * self,
@@ -918,9 +1170,7 @@ port_send_data_to_jack (
const int start_frame,
const int nframes)
{
- if (self->identifier.owner_type ==
- PORT_OWNER_TYPE_BACKEND ||
- self->internal_type !=
+ if (self->internal_type !=
INTERNAL_JACK_PORT ||
self->identifier.flow !=
FLOW_OUTPUT)
@@ -936,157 +1186,6 @@ port_send_data_to_jack (
}
/**
- * First sets port buf to 0, then sums the given
- * port signal from its inputs.
- *
- * @param start_frame The start frame offset from
- * 0 in this cycle.
- * @param nframes The number of frames to process.
- * @param noroll Clear the port buffer in this
- * range.
- */
-void
-port_sum_signal_from_inputs (
- Port * port,
- const int start_frame,
- const int nframes,
- const int noroll)
-{
- Port * src_port;
- int k, l;
-
- g_warn_if_fail (
- start_frame + nframes <=
- AUDIO_ENGINE->nframes);
-
- switch (port->identifier.type)
- {
- case TYPE_EVENT:
- if (noroll)
- break;
-
- port_sum_data_from_jack (
- port, start_frame, nframes);
-
- for (k = 0; k < port->num_srcs; k++)
- {
- src_port = port->srcs[k];
- g_warn_if_fail (
- src_port->identifier.type ==
- TYPE_EVENT);
- midi_events_append (
- src_port->midi_events,
- port->midi_events, start_frame,
- nframes, 0);
- }
-
- port_send_data_to_jack (
- port, start_frame, nframes);
-
- /* send UI notification */
- if (port->midi_events->num_events > 0)
- {
- g_message ("port %s has %d events",
- port->identifier.label,
- port->midi_events->num_events);
- /*if (port == AUDIO_ENGINE->midi_in)*/
- /*{*/
- /*AUDIO_ENGINE->trigger_midi_activity = 1;*/
- /*}*/
- if (port->identifier.owner_type ==
- PORT_OWNER_TYPE_TRACK)
- {
- port->track->trigger_midi_activity = 1;
- }
- }
- break;
- case TYPE_AUDIO:
- if (noroll)
- {
- for (l = start_frame; l < nframes; l++)
- {
- port->buf[l] = 0;
- }
- break;
- }
-
- port_sum_data_from_jack (
- port, start_frame, nframes);
-
- for (k = 0; k < port->num_srcs; k++)
- {
- src_port = port->srcs[k];
-
- /* sum the signals */
- /*g_message ("port %s start frame %ld nframes %d",*/
- /*port->identifier.label,*/
- /*start_frame, nframes);*/
- for (l = start_frame; l < nframes; l++)
- {
- port->buf[l] += src_port->buf[l];
- }
- }
-
- port_send_data_to_jack (
- port, start_frame, nframes);
- break;
- case TYPE_CONTROL:
- {
- float maxf, minf, depth_range, val_to_use;
- /* whether this is the first CV processed
- * on this control port */
- int first_cv = 1;
- for (k = 0; k < port->num_srcs; k++)
- {
- src_port = port->srcs[k];
-
- if (src_port->identifier.type ==
- TYPE_CV)
- {
- maxf =
- port->lv2_port->lv2_control->maxf;
- minf =
- port->lv2_port->lv2_control->minf;
- /*float deff =*/
- /*port->lv2_port->lv2_control->deff;*/
- /*port->lv2_port->control =*/
- /*deff + (maxf - deff) **/
- /*src_port->buf[0];*/
- depth_range =
- (maxf - minf) / 2.f;
-
- /* figure out whether to use base
- * value or the current value */
- if (first_cv)
- {
- val_to_use = port->base_value;
- first_cv = 0;
- }
- else
- val_to_use =
- port->lv2_port->control;
-
- /* TODO replace 1.f with modulator
- * depth */
- port->lv2_port->control =
- CLAMP (
- val_to_use +
- depth_range * src_port->buf[0] *
- src_port->multipliers[
- port_get_dest_index (
- src_port, port)],
- minf, maxf);
- }
- }
- }
- break;
- default:
- break;
- }
-}
-
-#ifdef HAVE_JACK
-/**
* Sets whether to expose the port to JACk and
* exposes it or removes it from JACK.
*/
@@ -1132,6 +1231,106 @@ port_set_expose_to_jack (
self->data = NULL;
}
}
+
+/**
+ * Returns the JACK port attached to this port,
+ * if any.
+ */
+jack_port_t *
+port_get_internal_jack_port (
+ Port * port)
+{
+ if (port->internal_type ==
+ INTERNAL_JACK_PORT &&
+ port->data)
+ return (jack_port_t *) port->data;
+ else
+ return NULL;
+}
+
+#endif
+
+#ifdef __linux__
+
+/**
+ * Returns the Port matching the given ALSA
+ * sequencer port ID.
+ */
+Port *
+port_find_by_alsa_seq_id (
+ const int id)
+{
+ Port * ports[10000];
+ int num_ports;
+ Port * port;
+ port_get_all (ports, &num_ports);
+ for (int i = 0; i < num_ports; i++)
+ {
+ port = ports[i];
+
+ if (port->internal_type ==
+ INTERNAL_ALSA_SEQ_PORT &&
+ snd_seq_port_info_get_port (
+ (snd_seq_port_info_t *) port->data) ==
+ id)
+ return port;
+ }
+ g_return_val_if_reached (NULL);
+}
+
+void
+port_set_expose_to_alsa (
+ Port * self,
+ int expose)
+{
+ if (self->identifier.type == TYPE_EVENT)
+ {
+ unsigned int flags = 0;
+ if (self->identifier.flow == FLOW_INPUT)
+ flags =
+ SND_SEQ_PORT_CAP_WRITE |
+ SND_SEQ_PORT_CAP_SUBS_WRITE;
+ else if (self->identifier.flow == FLOW_OUTPUT)
+ flags =
+ SND_SEQ_PORT_CAP_READ |
+ SND_SEQ_PORT_CAP_SUBS_READ;
+ else
+ g_return_if_reached ();
+
+ if (expose)
+ {
+ char * lbl =
+ port_get_full_designation (self);
+
+ int id =
+ snd_seq_create_simple_port (
+ AUDIO_ENGINE->seq_handle,
+ lbl, flags,
+ SND_SEQ_PORT_TYPE_APPLICATION);
+ g_return_if_fail (id >= 0);
+ snd_seq_port_info_t * info = NULL;
+ snd_seq_get_port_info (
+ AUDIO_ENGINE->seq_handle,
+ id, info);
+ self->data =
+ (void *) info;
+ g_free (lbl);
+ self->internal_type =
+ INTERNAL_ALSA_SEQ_PORT;
+ }
+ else
+ {
+ snd_seq_delete_port (
+ AUDIO_ENGINE->seq_handle,
+ snd_seq_port_info_get_port (
+ (snd_seq_port_info_t *)
+ self->data));
+ self->internal_type = INTERNAL_NONE;
+ self->data = NULL;
+ }
+ }
+}
+
#endif
/**
@@ -1169,6 +1368,11 @@ port_get_full_designation (
self->track->name,
id->label);
break;
+ case PORT_OWNER_TYPE_MONITOR_FADER:
+ return
+ g_strdup_printf (
+ "Engine/%s",
+ id->label);
default:
g_return_val_if_reached (NULL);
}
diff --git a/src/audio/routing.c b/src/audio/routing.c
index 97f4cd3..3708073 100644
--- a/src/audio/routing.c
+++ b/src/audio/routing.c
@@ -166,6 +166,10 @@ get_node_name (
"%s Pre-Fader",
node->prefader->channel->track->name);
break;
+ case ROUTE_NODE_TYPE_MONITOR_FADER:
+ return
+ g_strdup ("Monitor Fader");
+ break;
case ROUTE_NODE_TYPE_SAMPLE_PROCESSOR:
return
g_strdup ("Sample Processor");
@@ -300,6 +304,12 @@ node_process (
fader_process (
node->fader, local_offset, nframes);
}
+ else if (node->type ==
+ ROUTE_NODE_TYPE_MONITOR_FADER)
+ {
+ fader_process (
+ node->fader, local_offset, nframes);
+ }
else if (node->type == ROUTE_NODE_TYPE_PREFADER)
{
passthrough_processor_process (
@@ -444,151 +454,6 @@ node_process (
}
}
- /* if JACK stereo out */
- else if (
- port->identifier.owner_type ==
- PORT_OWNER_TYPE_BACKEND &&
- port->identifier.type == TYPE_AUDIO &&
- port->identifier.flow == FLOW_OUTPUT)
- {
- if (!AUDIO_ENGINE->exporting)
- {
- float * out;
- int ret;
- switch (AUDIO_ENGINE->audio_backend)
- {
- case AUDIO_BACKEND_JACK:
- if (port->internal_type !=
- INTERNAL_JACK_PORT)
- {
- g_warn_if_reached ();
- break;
- }
-#ifdef HAVE_JACK
- out =
- (float *)
- jack_port_get_buffer (
- JACK_PORT_T (port->data),
- AUDIO_ENGINE->nframes);
-
- /* by this time, the Master
- * channel should have its
- * Stereo Out ports filled.
- * pass their buffers to JACK's
- * buffers */
- for (i = 0; i < port->num_srcs;
- i++)
- {
- for (j = local_offset;
- j < local_offset +
- nframes;
- j++)
- {
- out[j] +=
- port->srcs[i]->buf[j];
- }
- }
-
- /* avoid unused warnings */
- (void) out;
-#endif
-
- break;
- case AUDIO_BACKEND_ALSA:
-#ifdef __linux__
- /* write interleaved */
- for (j = 0; j < port->num_srcs;
- j++)
- {
- if (port ==
- AUDIO_ENGINE->
- stereo_out->l)
- for (i = local_offset;
- i < local_offset +
- nframes;
- i++)
- {
- AUDIO_ENGINE->
- alsa_out_buf[i * 2] +=
- port->
- srcs[j]->buf[i];
- }
- else if (port ==
- AUDIO_ENGINE->
- stereo_out->r)
- for (i = local_offset;
- i < local_offset +
- nframes;
- i++)
- {
- AUDIO_ENGINE->
- alsa_out_buf[
- i * 2 + 1] +=
- port->srcs[j]->buf[i];
- }
- }
-#endif
- break;
- case AUDIO_BACKEND_PORT_AUDIO:
-#ifdef HAVE_PORT_AUDIO
- if (g_atomic_int_get (
- &AUDIO_ENGINE->
- filled_stereo_out_bufs))
- break;
- ret =
- g_atomic_int_compare_and_exchange (
- &AUDIO_ENGINE->
- filled_stereo_out_bufs,
- 0, 1);
- if (ret)
- engine_pa_fill_stereo_out_buffs (
- AUDIO_ENGINE);
-#endif
- break;
- case AUDIO_BACKEND_DUMMY:
- break;
- default:
- break;
- }
- }
- }
-
- /* if JACK MIDI out */
- else if (port->identifier.owner_type ==
- PORT_OWNER_TYPE_BACKEND &&
- port->identifier.type == TYPE_EVENT &&
- port->identifier.flow == FLOW_OUTPUT)
- {
- if (!AUDIO_ENGINE->exporting)
- {
- /*float * out;*/
- /*int ret;*/
- switch (AUDIO_ENGINE->audio_backend)
- {
- case AUDIO_BACKEND_JACK:
-#ifdef HAVE_JACK
- /* by this time, the Master
- * channel should have its
- * MIDI out port filled.
- * pass its buffer to JACK */
- port_sum_signal_from_inputs (
- port, local_offset,
- nframes, noroll);
-
- midi_events_copy_to_jack (
- port->midi_events,
- jack_port_get_buffer (
- JACK_PORT_T (port->data),
- AUDIO_ENGINE->nframes));
-#endif
- break;
- default:
- /* TODO */
- break;
- }
- }
- }
-
else
{
port_sum_signal_from_inputs (
@@ -992,6 +857,23 @@ find_node_from_sample_processor (
return NULL;
}
+static GraphNode *
+find_node_from_monitor_fader (
+ Graph * graph,
+ Fader * fader)
+{
+ GraphNode * node;
+ for (int i = 0; i < graph->n_graph_nodes; i++)
+ {
+ node = graph->graph_nodes[i];
+ if (node->type ==
+ ROUTE_NODE_TYPE_MONITOR_FADER &&
+ node->fader == fader)
+ return node;
+ }
+ return NULL;
+}
+
static inline GraphNode *
graph_node_new (
Graph * graph,
@@ -1009,6 +891,8 @@ graph_node_new (
node->port = (Port *) data;
else if (type == ROUTE_NODE_TYPE_FADER)
node->fader = (Fader *) data;
+ else if (type == ROUTE_NODE_TYPE_MONITOR_FADER)
+ node->fader = (Fader *) data;
else if (type == ROUTE_NODE_TYPE_PREFADER)
node->prefader = (PassthroughProcessor *) data;
else if (type ==
@@ -1309,6 +1193,7 @@ add_port (
port->num_srcs == 0 &&
owner != PORT_OWNER_TYPE_PLUGIN &&
owner != PORT_OWNER_TYPE_FADER &&
+ owner != PORT_OWNER_TYPE_MONITOR_FADER &&
owner != PORT_OWNER_TYPE_PREFADER)
{
}
@@ -1317,6 +1202,8 @@ add_port (
port->identifier.flow == FLOW_OUTPUT) &&
!(owner == PORT_OWNER_TYPE_FADER &&
port->identifier.flow == FLOW_OUTPUT) &&
+ !(owner == PORT_OWNER_TYPE_MONITOR_FADER &&
+ port->identifier.flow == FLOW_OUTPUT) &&
!(owner == PORT_OWNER_TYPE_PREFADER &&
port->identifier.flow == FLOW_OUTPUT) &&
!(owner ==
@@ -1332,6 +1219,9 @@ add_port (
!(owner == PORT_OWNER_TYPE_FADER &&
port->identifier.flow ==
FLOW_INPUT) &&
+ !(owner == PORT_OWNER_TYPE_MONITOR_FADER &&
+ port->identifier.flow ==
+ FLOW_INPUT) &&
!(owner == PORT_OWNER_TYPE_PREFADER &&
port->identifier.flow ==
FLOW_INPUT) &&
@@ -1526,6 +1416,11 @@ graph_new (
self, ROUTE_NODE_TYPE_SAMPLE_PROCESSOR,
SAMPLE_PROCESSOR);
+ /* add the monitor fader */
+ graph_add_node ( \
+ self, ROUTE_NODE_TYPE_MONITOR_FADER,
+ &AUDIO_ENGINE->monitor_fader);
+
/* add plugins */
Track * tr;
Plugin * pl;
@@ -1620,6 +1515,27 @@ graph_new (
find_node_from_port (self, port);
node_connect (node, node2);
+ /* connect the monitor fader */
+ node =
+ find_node_from_monitor_fader (
+ self, &AUDIO_ENGINE->monitor_fader);
+ port = AUDIO_ENGINE->monitor_fader.stereo_in->l;
+ node2 =
+ find_node_from_port (self, port);
+ node_connect (node2, node);
+ port = AUDIO_ENGINE->monitor_fader.stereo_in->r;
+ node2 =
+ find_node_from_port (self, port);
+ node_connect (node2, node);
+ port = AUDIO_ENGINE->monitor_fader.stereo_out->l;
+ node2 =
+ find_node_from_port (self, port);
+ node_connect (node, node2);
+ port = AUDIO_ENGINE->monitor_fader.stereo_out->r;
+ node2 =
+ find_node_from_port (self, port);
+ node_connect (node, node2);
+
Fader * fader;
PassthroughProcessor * prefader;
for (int i = 0; i < TRACKLIST->num_tracks; i++)
diff --git a/src/audio/track.c b/src/audio/track.c
index aad98d2..ed54872 100644
--- a/src/audio/track.c
+++ b/src/audio/track.c
@@ -704,12 +704,38 @@ track_set_pos (
if (track->channel)
{
Channel * ch = track->channel;
- ch->stereo_out->l->identifier.track_pos = pos;
- ch->stereo_out->r->identifier.track_pos = pos;
- ch->stereo_in->l->identifier.track_pos = pos;
- ch->stereo_in->r->identifier.track_pos = pos;
- ch->midi_in->identifier.track_pos = pos;
- ch->piano_roll->identifier.track_pos = pos;
+
+ if (track->in_signal_type ==
+ TYPE_AUDIO)
+ {
+ ch->stereo_in->l->identifier.track_pos =
+ pos;
+ ch->stereo_in->r->identifier.track_pos =
+ pos;
+ }
+ if (track->in_signal_type ==
+ TYPE_EVENT)
+ {
+ ch->midi_in->identifier.track_pos =
+ pos;
+ if (track_has_piano_roll (track))
+ ch->piano_roll->identifier.track_pos =
+ pos;
+ }
+ if (track->out_signal_type ==
+ TYPE_AUDIO)
+ {
+ ch->stereo_out->l->identifier.track_pos =
+ pos;
+ ch->stereo_out->r->identifier.track_pos =
+ pos;
+ }
+ if (track->out_signal_type ==
+ TYPE_EVENT)
+ {
+ ch->midi_out->identifier.track_pos =
+ pos;
+ }
}
}
diff --git a/src/gui/widgets/channel.c b/src/gui/widgets/channel.c
index 94922c0..f69accf 100644
--- a/src/gui/widgets/channel.c
+++ b/src/gui/widgets/channel.c
@@ -75,6 +75,15 @@ channel_widget_update_meter_reading (
double prev = widget->meter_reading_val;
Channel * channel = widget->channel;
+ /* TODO */
+ if (channel->track->out_signal_type ==
+ TYPE_EVENT)
+ {
+ gtk_label_set_text (
+ widget->meter_reading, "-∞");
+ return FALSE;
+ }
+
/* calc decibels */
channel_set_current_l_db (
channel,
diff --git a/src/gui/widgets/inspector_track.c b/src/gui/widgets/inspector_track.c
index 5f16acb..4d09185 100644
--- a/src/gui/widgets/inspector_track.c
+++ b/src/gui/widgets/inspector_track.c
@@ -20,7 +20,7 @@
#include "gui/backend/events.h"
#include "gui/backend/tracklist_selections.h"
#include "gui/widgets/inspector_track.h"
-#include "gui/widgets/instrument_track_info_expander.h"
+#include "gui/widgets/track_properties_expander.h"
#include "gui/widgets/ports_expander.h"
#include "project.h"
#include "utils/resources.h"
@@ -44,18 +44,18 @@ inspector_track_widget_show_tracks (
{
track = tls->tracks[0];
- instrument_track_info_expander_widget_setup (
+ track_properties_expander_widget_setup (
self->instrument_track_info,
track);
gtk_widget_set_visible (
GTK_WIDGET (self->sends), 0);
- gtk_widget_set_visible (
- GTK_WIDGET (self->stereo_in), 0);
- gtk_widget_set_visible (
- GTK_WIDGET (self->midi_in), 0);
- gtk_widget_set_visible (
- GTK_WIDGET (self->midi_out), 0);
+ /*gtk_widget_set_visible (*/
+ /*GTK_WIDGET (self->stereo_in), 0);*/
+ /*gtk_widget_set_visible (*/
+ /*GTK_WIDGET (self->midi_in), 0);*/
+ /*gtk_widget_set_visible (*/
+ /*GTK_WIDGET (self->midi_out), 0);*/
if (track->channel)
{
@@ -114,9 +114,6 @@ inspector_track_widget_class_init (
BIND_CHILD (instrument_track_info);
BIND_CHILD (sends);
- BIND_CHILD (stereo_in);
- BIND_CHILD (midi_in);
- BIND_CHILD (midi_out);
#undef BIND_CHILD
}
@@ -126,7 +123,7 @@ inspector_track_widget_init (
InspectorTrackWidget * self)
{
g_type_ensure (
- INSTRUMENT_TRACK_INFO_EXPANDER_WIDGET_TYPE);
+ TRACK_PROPERTIES_EXPANDER_WIDGET_TYPE);
gtk_widget_init_template (GTK_WIDGET (self));
}
diff --git a/src/gui/widgets/live_waveform.c b/src/gui/widgets/live_waveform.c
index 9c1aa6f..801b94b 100644
--- a/src/gui/widgets/live_waveform.c
+++ b/src/gui/widgets/live_waveform.c
@@ -78,10 +78,8 @@ live_waveform_draw_cb (
{
val =
MAX (
- P_MASTER_TRACK->channel->
- stereo_out->l->buf[i],
- P_MASTER_TRACK->channel->
- stereo_out->r->buf[i]);
+ AUDIO_ENGINE->monitor_out->l->buf[i],
+ AUDIO_ENGINE->monitor_out->r->buf[i]);
cairo_line_to (
cr, width * ((double) i / nframes),
diff --git a/src/gui/widgets/meson.build b/src/gui/widgets/meson.build
index 92c80f2..062e6e8 100644
--- a/src/gui/widgets/meson.build
+++ b/src/gui/widgets/meson.build
@@ -81,7 +81,7 @@ widget_srcs = [
'inspector_plugin.c',
'inspector_track.c',
'instrument_track.c',
- 'instrument_track_info_expander.c',
+ 'track_properties_expander.c',
'knob.c',
'knob_with_name.c',
'left_dock_edge.c',
diff --git a/src/gui/widgets/instrument_track_info_expander.c b/src/gui/widgets/track_properties_expander.c
index bb6a411..4d1884d 100644
--- a/src/gui/widgets/instrument_track_info_expander.c
+++ b/src/gui/widgets/track_properties_expander.c
@@ -21,32 +21,32 @@
#include "audio/mixer.h"
#include "audio/track.h"
#include "gui/widgets/editable_label.h"
-#include "gui/widgets/instrument_track_info_expander.h"
+#include "gui/widgets/track_properties_expander.h"
#include "project.h"
#include <glib/gi18n.h>
-G_DEFINE_TYPE (InstrumentTrackInfoExpanderWidget,
- instrument_track_info_expander_widget,
+G_DEFINE_TYPE (TrackPropertiesExpanderWidget,
+ track_properties_expander_widget,
TWO_COL_EXPANDER_BOX_WIDGET_TYPE)
/**
* Refreshes each field.
*/
void
-instrument_track_info_expander_widget_refresh (
- InstrumentTrackInfoExpanderWidget * self)
+track_properties_expander_widget_refresh (
+ TrackPropertiesExpanderWidget * self)
{
/* TODO */
}
/**
- * Sets up the InstrumentTrackInfoExpanderWidget.
+ * Sets up the TrackPropertiesExpanderWidget.
*/
void
-instrument_track_info_expander_widget_setup (
- InstrumentTrackInfoExpanderWidget * self,
+track_properties_expander_widget_setup (
+ TrackPropertiesExpanderWidget * self,
Track * track)
{
g_warn_if_fail (track);
@@ -55,19 +55,19 @@ instrument_track_info_expander_widget_setup (
editable_label_widget_setup (
self->name,
track, track_get_name, track_set_name);
- instrument_track_info_expander_widget_refresh (
+ track_properties_expander_widget_refresh (
self);
}
static void
-instrument_track_info_expander_widget_class_init (
- InstrumentTrackInfoExpanderWidgetClass * klass)
+track_properties_expander_widget_class_init (
+ TrackPropertiesExpanderWidgetClass * klass)
{
}
static void
-instrument_track_info_expander_widget_init (
- InstrumentTrackInfoExpanderWidget * self)
+track_properties_expander_widget_init (
+ TrackPropertiesExpanderWidget * self)
{
self->name =
editable_label_widget_new (