Browse Source

add prefader processor

carla_vst
Alexandros Theodotou 4 years ago
parent
commit
4bb4a77f0f
Signed by: alex
GPG Key ID: 022EAE42313D70F3
  1. 4
      INSTALL.md
  2. 28
      README.md
  3. 2
      THANKS
  4. 0
      data/fonts/DSEG14-Classic-MINI/DSEG-LICENSE.txt
  5. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Bold.ttf
  6. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Bold.woff
  7. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Bold.woff2
  8. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-BoldItalic.ttf
  9. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-BoldItalic.woff
  10. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-BoldItalic.woff2
  11. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Italic.ttf
  12. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Italic.woff
  13. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Italic.woff2
  14. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Light.ttf
  15. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Light.woff
  16. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Light.woff2
  17. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-LightItalic.ttf
  18. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-LightItalic.woff
  19. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-LightItalic.woff2
  20. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Regular.ttf
  21. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Regular.woff
  22. 0
      data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Regular.woff2
  23. 0
      data/fonts/DSEG14-Classic-MINI/README.md
  24. 15
      data/meson.build
  25. 0
      data/samples/klick/COPYING
  26. 0
      data/samples/klick/square_emphasis.wav
  27. 0
      data/samples/klick/square_normal.wav
  28. 31
      doc/user/README.md
  29. 4
      inc/audio/channel.h
  30. 135
      inc/audio/passthrough_processor.h
  31. 11
      inc/audio/port.h
  32. 27
      inc/audio/routing.h
  33. 5
      inc/gui/widgets/inspector_track.h
  34. 20
      inc/gui/widgets/ports_expander.h
  35. 94
      resources/fonts/Segment7Standard/OFL.txt
  36. BIN
      resources/fonts/Segment7Standard/Segment7Standard.otf
  37. 20
      resources/meson.build
  38. 14
      resources/ui/inspector_track.ui
  39. 81
      src/audio/channel.c
  40. 1
      src/audio/meson.build
  41. 123
      src/audio/passthrough_processor.c
  42. 46
      src/audio/port.c
  43. 69
      src/audio/routing.c
  44. 61
      src/gui/widgets/inspector_plugin.c
  45. 13
      src/gui/widgets/inspector_track.c
  46. 8
      src/gui/widgets/port_connections_button.c
  47. 8
      src/gui/widgets/port_connections_popover.c
  48. 348
      src/gui/widgets/ports_expander.c

4
INSTALL.md

@ -51,10 +51,6 @@ location so `XDG_DATA_DIRS` might be a better idea. @@ -51,10 +51,6 @@ location so `XDG_DATA_DIRS` might be a better idea.
Generally, we recommend installing under `/usr/local`
(default) or `/usr` to avoid these problems.
## Binary Packages
For easy package installation see
[Installation](https://manual.zrythm.org/en/configuration/installation/intro.html) in the manual.
----
Copyright (C) 2019 Alexandros Theodotou

28
README.md

@ -20,13 +20,15 @@ Zrythm is currently in alpha. @@ -20,13 +20,15 @@ Zrythm is currently in alpha.
## Currently supported plugin protocols:
- LV2
## Installation
## Building and Installation
See [INSTALL.md](INSTALL.md).
## Using
At the moment, Zrythm works with Jack (recommended) and ALSA. For Jack setup instructions see https://libremusicproduction.com/articles/demystifying-jack-%E2%80%93-beginners-guide-getting-started-jack
At the moment, Zrythm works with Jack (recommended) and ALSA.
For Jack setup instructions see
https://libremusicproduction.com/articles/demystifying-jack-%E2%80%93-beginners-guide-getting-started-jack
For more information see the [manual](https://manual.zrythm.org).
For more information see the [user manual](doc/user/README.md).
## Packaging
See [PACKAGING.md](PACKAGING.md).
@ -38,19 +40,24 @@ For contributing guidelines see [CONTRIBUTING.md](CONTRIBUTING.md). Be sure to t @@ -38,19 +40,24 @@ For contributing guidelines see [CONTRIBUTING.md](CONTRIBUTING.md). Be sure to t
For any bugs please raise an issue or join a chatroom below
## Chatrooms
### Matrix/IRC (Freenode)
`#zrythm` channel (for Matrix users `#zrythmdaw:matrix.org`)
`#zrythm` channel on freenode (for Matrix users `#zrythmdaw:matrix.org`).
## Mailing lists
zrythm-dev@nongnu.org for developers, zrythm-user@nongnu.org for users
## Bug Tracker
https://savannah.nongnu.org/support/?group=zrythm
## Releases
https://savannah.nongnu.org/files/?group=zrythm
## License
This program is free software: you can redistribute it and/or modify
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.
This program is distributed in the hope that it will be useful,
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.
@ -63,8 +70,13 @@ listing individual years (โ€œ2008, 2009, 2010โ€) if and only if every year @@ -63,8 +70,13 @@ listing individual years (โ€œ2008, 2009, 2010โ€) if and only if every year
in the range, inclusive, is a โ€œcopyrightableโ€ year that would be listed
individually.
Some files, where specified, are licensed under
different licenses.
## Support
We appreciate contributions of any size -- donations enable us to spend more time working on the project, and help cover our infrastructure expenses.
We appreciate contributions of any size -- donations
enable us to spend more time working on the project,
and help cover our infrastructure expenses.
### Paypal
https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=LZWVK6228PQGE&source=url

2
THANKS

@ -12,7 +12,7 @@ Thanks: @@ -12,7 +12,7 @@ Thanks:
* Coming up with the Zrythm tagline
Yuri
* FreeBSD packager
Robin Gareus <robin@gareus.org>
Robin Gareus <https://gareus.org/>
* Help and advice
* Routing algorithm
* Latency compensation algorithm

0
resources/fonts/DSEG14-Classic-MINI/DSEG-LICENSE.txt → data/fonts/DSEG14-Classic-MINI/DSEG-LICENSE.txt

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Bold.ttf → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Bold.ttf

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Bold.woff → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Bold.woff

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Bold.woff2 → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Bold.woff2

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-BoldItalic.ttf → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-BoldItalic.ttf

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-BoldItalic.woff → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-BoldItalic.woff

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-BoldItalic.woff2 → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-BoldItalic.woff2

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Italic.ttf → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Italic.ttf

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Italic.woff → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Italic.woff

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Italic.woff2 → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Italic.woff2

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Light.ttf → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Light.ttf

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Light.woff → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Light.woff

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Light.woff2 → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Light.woff2

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-LightItalic.ttf → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-LightItalic.ttf

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-LightItalic.woff → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-LightItalic.woff

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-LightItalic.woff2 → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-LightItalic.woff2

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Regular.ttf → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Regular.ttf

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Regular.woff → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Regular.woff

0
resources/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Regular.woff2 → data/fonts/DSEG14-Classic-MINI/DSEG14ClassicMini-Regular.woff2

0
resources/fonts/DSEG14-Classic-MINI/README.md → data/fonts/DSEG14-Classic-MINI/README.md

15
data/meson.build

@ -19,6 +19,21 @@ install_data ( @@ -19,6 +19,21 @@ install_data (
'org.zrythm.Zrythm.gschema.xml',
install_dir: schemasdir)
# install fonts
install_subdir (
join_paths ('fonts', 'DSEG14-Classic-MINI'),
install_dir: join_paths (fontsdir))
#install samples
install_data (
join_paths (
'samples', 'klick', 'square_emphasis.wav'),
install_dir: samplesdir)
install_data (
join_paths (
'samples', 'klick', 'square_normal.wav'),
install_dir: samplesdir)
# Desktop launcher and description file.
desktop_file = i18n.merge_file (
input: 'zrythm.desktop.in',

0
resources/samples/klick/COPYING → data/samples/klick/COPYING

0
resources/samples/klick/square_emphasis.wav → data/samples/klick/square_emphasis.wav

0
resources/samples/klick/square_normal.wav → data/samples/klick/square_normal.wav

31
doc/user/README.md

@ -1,27 +1,28 @@ @@ -1,27 +1,28 @@
# zrythm-docs
Zrythm User Manual
==================
Documentation generator for the Zrythm manual.
Zrythm user manual generator using
[sphinx-build](http://sphinx-doc.org/).
# Website
## Usage Example
For bundling for the website, use `make bundle` and it will create a
deployable `_rendered` folder. Just rsync that and done.
Use `make html` to build the manual in HTML.
Type `make` to see the available output formats.
Example: https://docs.zrythm.org
# man
## Website
Use `make man` and it will generate a man page for each language.
For bundling for the website, use `make bundle`
and it will create a deployable `_rendered`
folder.
# Other Formats
Type `make` and it will show all the options.
Example: https://docs.zrythm.org
# Note About PDFs
## Note About PDFs
PDF compilation requires texlive. See https://tug.org/texlive/quickinstall.html
PDF compilation requires texlive. See
https://tug.org/texlive/quickinstall.html
# LICENSE
## LICENSE
The sources required to build the manual and the
contents of the manual are licensed under the GNU
Affero General Public License, version 3 or later.

4
inc/audio/channel.h

@ -31,6 +31,7 @@ @@ -31,6 +31,7 @@
#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"
@ -116,6 +117,9 @@ typedef struct Channel @@ -116,6 +117,9 @@ typedef struct Channel
/** The channel fader. */
Fader fader;
/** Prefader. */
PassthroughProcessor prefader;
/**
* L & R audio input ports.
*/

135
inc/audio/passthrough_processor.h

@ -0,0 +1,135 @@ @@ -0,0 +1,135 @@
/*
* 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/>.
*/
/**
* \file
*
* A simple processor that copies the buffers of its
* inputs to its outputs.
*/
#ifndef __AUDIO_PASSTHROUGH_PROCESSOR_H__
#define __AUDIO_PASSTHROUGH_PROCESSOR_H__
#include "utils/yaml.h"
typedef struct StereoPorts StereoPorts;
/**
* @addtogroup audio
*
* @{
*/
typedef struct Channel Channel;
/**
* A simple processor that copies the buffers of its
* inputs to its outputs.
*
* Used for the pre fader processor.
*/
typedef struct PassthroughProcessor
{
/** 0.0 ~ 1.0 for widgets. */
float passthrough_processor_val;
/**
* L & R audio input ports.
*/
StereoPorts * stereo_in;
/**
* L & R audio output ports.
*/
StereoPorts * stereo_out;
/**
* Current dBFS after procesing each output port.
*
* Transient variables only used by the GUI.
*/
float l_port_db;
float r_port_db;
/** Owner channel. */
Channel * channel;
} PassthroughProcessor;
static const cyaml_schema_field_t
passthrough_processor_fields_schema[] =
{
CYAML_FIELD_END
};
static const cyaml_schema_value_t
passthrough_processor_schema =
{
CYAML_VALUE_MAPPING (
CYAML_FLAG_POINTER,
PassthroughProcessor,
passthrough_processor_fields_schema),
};
/**
* Inits passthrough_processor to default values.
*
* @param self The PassthroughProcessor to init.
* @param ch Channel.
*/
void
passthrough_processor_init (
PassthroughProcessor * self,
Channel * ch);
/**
* Sets the passthrough_processor levels from a normalized value
* 0.0-1.0 (such as in widgets).
*/
void
passthrough_processor_set_widget_val (
PassthroughProcessor * self,
float val);
/**
* Copy the struct members from source to dest.
*/
void
passthrough_processor_copy (
PassthroughProcessor * src,
PassthroughProcessor * dest);
/**
* Process the PassthroughProcessor.
*
* @param g_frames The global start frames.
* @param nframes The number of frames to process.
*/
void
passthrough_processor_process (
PassthroughProcessor * self,
long g_frames,
int nframes);
/**
* @}
*/
#endif

11
inc/audio/port.h

@ -33,6 +33,8 @@ typedef struct Plugin Plugin; @@ -33,6 +33,8 @@ typedef struct Plugin Plugin;
typedef struct MidiEvents MidiEvents;
typedef struct Fader Fader;
typedef struct SampleProcessor SampleProcessor;
typedef struct PassthroughProcessor
PassthroughProcessor;
/**
* @addtogroup audio
@ -80,6 +82,7 @@ typedef enum PortOwnerType @@ -80,6 +82,7 @@ typedef enum PortOwnerType
PORT_OWNER_TYPE_BACKEND,
PORT_OWNER_TYPE_PLUGIN,
PORT_OWNER_TYPE_TRACK,
PORT_OWNER_TYPE_PREFADER,
PORT_OWNER_TYPE_FADER,
PORT_OWNER_TYPE_SAMPLE_PROCESSOR,
} PortOwnerType;
@ -620,6 +623,14 @@ port_set_owner_fader ( @@ -620,6 +623,14 @@ port_set_owner_fader (
Port * port,
Fader * fader);
/**
* Sets the owner fader & its ID.
*/
void
port_set_owner_prefader (
Port * port,
PassthroughProcessor * fader);
/**
* Sets the owner plugin & its ID.
*/

27
inc/audio/routing.h

@ -17,7 +17,10 @@ @@ -17,7 +17,10 @@
* along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
*/
/** \file
/**
* \file
*
* Routing graph.
*/
#ifndef __AUDIO_ROUTING_H__
@ -26,6 +29,17 @@ @@ -26,6 +29,17 @@
#include <pthread.h>
#include "zix/sem.h"
typedef struct GraphNode GraphNode;
typedef struct Graph Graph;
typedef struct PassthroughProcessor
PassthroughProcessor;
/**
* @addtogroup audio
*
* @{
*/
/**
* Graph nodes can be either ports or processors.
*
@ -39,12 +53,12 @@ typedef enum GraphNodeType @@ -39,12 +53,12 @@ typedef enum GraphNodeType
ROUTE_NODE_TYPE_PLUGIN,
/** Fader/pan processor. */
ROUTE_NODE_TYPE_FADER,
/** Pre-Fader passthrough processor. */
ROUTE_NODE_TYPE_PREFADER,
/** Sample processor. */
ROUTE_NODE_TYPE_SAMPLE_PROCESSOR,
} GraphNodeType;
typedef struct GraphNode GraphNode;
typedef struct Graph Graph;
typedef struct GraphNode
{
int id;
@ -75,6 +89,9 @@ typedef struct GraphNode @@ -75,6 +89,9 @@ typedef struct GraphNode
/** Fader, if fader. */
Fader * fader;
/** Pre-Fader, if prefader node. */
PassthroughProcessor * prefader;
/** Sample processor, if sample processor. */
SampleProcessor * sample_processor;
@ -239,4 +256,8 @@ void @@ -239,4 +256,8 @@ void
graph_destroy (
Graph * graph);
/**
* @}
*/
#endif

5
inc/gui/widgets/inspector_track.h

@ -34,12 +34,17 @@ typedef struct TracklistSelections @@ -34,12 +34,17 @@ typedef struct TracklistSelections
TracklistSelections;
typedef struct _InstrumentTrackInfoExpanderWidget
InstrumentTrackInfoExpanderWidget;
typedef struct _PortsExpanderWidget
PortsExpanderWidget;
typedef struct _InspectorTrackWidget
{
GtkBox parent_instance;
InstrumentTrackInfoExpanderWidget *
instrument_track_info;
PortsExpanderWidget * prefader_sends;
PortsExpanderWidget * postfader_sends;
} InspectorTrackWidget;
void

20
inc/gui/widgets/ports_expander.h

@ -69,15 +69,25 @@ ports_expander_widget_refresh ( @@ -69,15 +69,25 @@ ports_expander_widget_refresh (
PortsExpanderWidget * self);
/**
* Sets up the PortsExpanderWidget.
* Sets up the PortsExpanderWidget for a Plugin.
*/
void
ports_expander_widget_setup (
ports_expander_widget_setup_plugin (
PortsExpanderWidget * self,
PortFlow flow,
PortType type,
PortOwnerType owner_type,
Plugin * pl,
Track * tr);
Plugin * pl);
/**
* Sets up the PortsExpanderWidget for Track sends.
*
* @param prefader 1 for pre-fader, 0 for
* post-fader.
*/
void
ports_expander_widget_setup_sends (
PortsExpanderWidget * self,
Track * tr,
int prefader);
#endif

94
resources/fonts/Segment7Standard/OFL.txt

@ -1,94 +0,0 @@ @@ -1,94 +0,0 @@
Copyright (c) 2014, Cedric Knight <fonts@cedders.com>,
with Reserved Font Name "Segment7".
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

BIN
resources/fonts/Segment7Standard/Segment7Standard.otf

Binary file not shown.

20
resources/meson.build

@ -15,22 +15,10 @@ @@ -15,22 +15,10 @@
# You should have received a copy of the GNU Affero General Public License
# along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
# install fonts
install_subdir (
join_paths ('fonts', 'DSEG14-Classic-MINI'),
install_dir: join_paths (fontsdir))
#install samples
install_data (
join_paths (
'samples/klick/square_emphasis.wav'),
install_dir: samplesdir)
install_data (
join_paths (
'samples/klick/square_normal.wav'),
install_dir: samplesdir)
# install app icon
install_data (
join_paths ('icons', 'zrythm', 'zrythm.svg'),
install_dir: join_paths (datadir, 'icons', 'hicolor', 'scalable', 'apps'))
install_dir:
join_paths (
datadir, 'icons', 'hicolor', 'scalable',
'apps'))

14
resources/ui/inspector_track.ui

@ -32,5 +32,19 @@ @@ -32,5 +32,19 @@
<property name="visible">True</property>
</object>
</child>
<child>
<object class="PortsExpanderWidget"
id="prefader_sends">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="PortsExpanderWidget"
id="postfader_sends">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</template>
</interface>

81
src/audio/channel.c

@ -138,10 +138,10 @@ disconnect_stereo_in_from_fader ( @@ -138,10 +138,10 @@ disconnect_stereo_in_from_fader (
{
port_disconnect (
ch->stereo_in->l,
ch->fader.stereo_in->l);
ch->prefader.stereo_in->l);
port_disconnect (
ch->stereo_in->r,
ch->fader.stereo_in->r);
ch->prefader.stereo_in->r);
}
/**
@ -156,10 +156,10 @@ connect_stereo_in_to_fader ( @@ -156,10 +156,10 @@ connect_stereo_in_to_fader (
{
port_connect (
ch->stereo_in->l,
ch->fader.stereo_in->l);
ch->prefader.stereo_in->l);
port_connect (
ch->stereo_in->r,
ch->fader.stereo_in->r);
ch->prefader.stereo_in->r);
}
/**
@ -415,10 +415,10 @@ connect_pl_to_fader ( @@ -415,10 +415,10 @@ connect_pl_to_fader (
{
port_connect (
out_port,
ch->fader.stereo_in->l);
ch->prefader.stereo_in->l);
port_connect (
out_port,
ch->fader.stereo_in->r);
ch->prefader.stereo_in->r);
break;
}
}
@ -438,14 +438,14 @@ connect_pl_to_fader ( @@ -438,14 +438,14 @@ connect_pl_to_fader (
{
port_connect (
out_port,
ch->fader.stereo_in->l);
ch->prefader.stereo_in->l);
last_index++;
}
else if (last_index == 1)
{
port_connect (
out_port,
ch->fader.stereo_in->r);
ch->prefader.stereo_in->r);
break;
}
}
@ -614,13 +614,13 @@ disconnect_pl_from_fader ( @@ -614,13 +614,13 @@ disconnect_pl_from_fader (
if (out_port->identifier.type == TYPE_AUDIO)
{
if (ports_connected (
out_port, ch->fader.stereo_in->l))
out_port, ch->prefader.stereo_in->l))
port_disconnect (
out_port, ch->fader.stereo_in->l);
out_port, ch->prefader.stereo_in->l);
if (ports_connected (
out_port, ch->fader.stereo_in->r))
out_port, ch->prefader.stereo_in->r))
port_disconnect (
out_port, ch->fader.stereo_in->r);
out_port, ch->prefader.stereo_in->r);
}
}
}
@ -995,6 +995,10 @@ channel_prepare_process (Channel * channel) @@ -995,6 +995,10 @@ channel_prepare_process (Channel * channel)
port_clear_buffer (channel->midi_in);
port_clear_buffer (channel->piano_roll);
}
port_clear_buffer (channel->prefader.stereo_in->l);
port_clear_buffer (channel->prefader.stereo_in->r);
port_clear_buffer (channel->prefader.stereo_out->l);
port_clear_buffer (channel->prefader.stereo_out->r);
port_clear_buffer (channel->fader.stereo_in->l);
port_clear_buffer (channel->fader.stereo_in->r);
port_clear_buffer (channel->fader.stereo_out->l);
@ -1039,6 +1043,7 @@ channel_init_loaded (Channel * ch) @@ -1039,6 +1043,7 @@ channel_init_loaded (Channel * ch)
g_warn_if_fail (ch->track);
/* fader */
ch->prefader.channel = ch;
ch->fader.channel = ch;
/* midi in / piano roll ports */
@ -1187,6 +1192,9 @@ _create_channel ( @@ -1187,6 +1192,9 @@ _create_channel (
&self->fader,
FADER_TYPE_CHANNEL,
self);
passthrough_processor_init (
&self->prefader,
self);
/* set up piano roll port */
char * tmp =
@ -1351,9 +1359,15 @@ channel_connect ( @@ -1351,9 +1359,15 @@ channel_connect (
* fader */
port_connect (
ch->stereo_in->l,
ch->fader.stereo_in->l);
ch->prefader.stereo_in->l);
port_connect (
ch->stereo_in->r,
ch->prefader.stereo_in->r);
port_connect (
ch->prefader.stereo_out->l,
ch->fader.stereo_in->l);
port_connect (
ch->prefader.stereo_out->r,
ch->fader.stereo_in->r);
port_connect (
ch->fader.stereo_out->l,
@ -1469,51 +1483,11 @@ channel_get_phase (void * _channel) @@ -1469,51 +1483,11 @@ channel_get_phase (void * _channel)
return channel->fader.phase;
}
/*void*/
/*channel_set_volume (void * _channel, float volume)*/
/*{*/
/*Channel * channel = (Channel *) _channel;*/
/*channel->volume = volume;*/
/*[> TODO update tooltip <]*/
/*gtk_label_set_text (channel->widget->phase_reading,*/
/*g_strdup_printf ("%.1f", volume));*/
/*g_idle_add ((GSourceFunc) gtk_widget_queue_draw,*/
/*GTK_WIDGET (channel->widget->fader));*/
/*}*/
/*float*/
/*channel_get_volume (void * _channel)*/
/*{*/
/*Channel * channel = (Channel *) _channel;*/
/*return channel->volume;*/
/*}*/
/*static int*/
/*redraw_fader_asnyc (Channel * channel)*/
/*{*/
/*gtk_widget_queue_draw (*/
/*GTK_WIDGET (channel->widget->fader));*/
/*return FALSE;*/
/*}*/
/*static int*/
/*redraw_pan_async (Channel * channel)*/
/*{*/
/*gtk_widget_queue_draw (*/
/*GTK_WIDGET (channel->widget->pan));*/
/*return FALSE;*/
/*}*/
void
channel_set_pan (void * _channel, float pan)
{
Channel * channel = (Channel *) _channel;
channel->fader.pan = pan;
/*g_idle_add ((GSourceFunc) redraw_pan_async,*/
/*channel);*/
}
float
@ -1980,6 +1954,7 @@ channel_clone ( @@ -1980,6 +1954,7 @@ channel_clone (
COPY_MEMBER (type);
clone->fader.channel = clone;
clone->prefader.channel = clone;
fader_copy (&ch->fader, &clone->fader);
#undef COPY_MEMBER

1
src/audio/meson.build

@ -53,6 +53,7 @@ audio_srcs = [ @@ -53,6 +53,7 @@ audio_srcs = [
'port.c',
'position.c',
'quantize_options.c',
'passthrough_processor.c',
'region.c',
'routing.c',
'sample_playback.c',

123
src/audio/passthrough_processor.c

@ -0,0 +1,123 @@ @@ -0,0 +1,123 @@
/*
* 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 "audio/channel.h"
#include "audio/engine.h"
#include "audio/passthrough_processor.h"
#include "audio/track.h"
#include "project.h"
#include "utils/math.h"
/**
* Inits passthrough_processor to default values.
*
* This assumes that the channel has no plugins.
*
* @param self The PassthroughProcessor to init.
* @param ch Channel.
*/
void
passthrough_processor_init (
PassthroughProcessor * self,
Channel * ch)
{
self->channel = ch;
self->l_port_db = 0.f;
self->r_port_db = 0.f;
/* stereo in */
char * pll =
g_strdup_printf (
"%s Pre-Fader in L",
ch->track->name);
char * plr =
g_strdup_printf (
"%s Pre-Fader in R",
ch->track->name);
self->stereo_in =
stereo_ports_new (
port_new_with_type (TYPE_AUDIO,
FLOW_INPUT,
pll),
port_new_with_type (TYPE_AUDIO,
FLOW_INPUT,
plr));
self->stereo_in->l->identifier.flags |=
PORT_FLAG_STEREO_L;
self->stereo_in->r->identifier.flags |=
PORT_FLAG_STEREO_R;
self->stereo_in->l->identifier.owner_type =
PORT_OWNER_TYPE_PREFADER;
self->stereo_in->r->identifier.owner_type =
PORT_OWNER_TYPE_PREFADER;
/* stereo out */
pll =
g_strdup_printf ("%s Pre-Fader out L",
ch->track->name);
plr =
g_strdup_printf ("%s Pre-Fader out R",
ch->track->name);
self->stereo_out =
stereo_ports_new (
port_new_with_type (TYPE_AUDIO,
FLOW_OUTPUT,
pll),
port_new_with_type (TYPE_AUDIO,
FLOW_OUTPUT,
plr));
self->stereo_out->l->identifier.flags |=
PORT_FLAG_STEREO_L;
self->stereo_out->r->identifier.flags |=
PORT_FLAG_STEREO_R;
port_set_owner_prefader (
self->stereo_in->l, self);
port_set_owner_prefader (
self->stereo_in->r, self);
port_set_owner_prefader (
self->stereo_out->l, self);
port_set_owner_prefader (
self->stereo_out->r, self);
}
/**
* Process the PassthroughProcessor.
*
* @param start_frame The local offset in this
* cycle.
* @param nframes The number of frames to process.
*/
void
passthrough_processor_process (
PassthroughProcessor * self,
long start_frame,
int nframes)
{
/* copy the input to output */
for (int i = start_frame;
i < start_frame + nframes; i++)
{
self->stereo_out->l->buf[i] =
self->stereo_in->l->buf[i];
self->stereo_out->r->buf[i] =
self->stereo_in->r->buf[i];
}
}

46
src/audio/port.c

@ -34,6 +34,7 @@ @@ -34,6 +34,7 @@
#include "audio/mixer.h"
#include "audio/modulator.h"
#include "audio/pan.h"
#include "audio/passthrough_processor.h"
#include "audio/port.h"
#include "plugins/plugin.h"
#include "utils/arrays.h"
@ -232,6 +233,28 @@ port_find_from_identifier ( @@ -232,6 +233,28 @@ port_find_from_identifier (
return ch->fader.stereo_in->r;
}
break;
case PORT_OWNER_TYPE_PREFADER:
tr = TRACKLIST->tracks[id->track_pos];
g_warn_if_fail (tr);
ch = tr->channel;
g_warn_if_fail (ch);
if (id->flow == FLOW_OUTPUT)
{
if (id->flags & PORT_FLAG_STEREO_L)
return ch->prefader.stereo_out->l;
else if (id->flags &
PORT_FLAG_STEREO_R)
return ch->prefader.stereo_out->r;
}
else if (id->flow == FLOW_INPUT)
{
if (id->flags & PORT_FLAG_STEREO_L)
return ch->prefader.stereo_in->r;
else if (id->flags &
PORT_FLAG_STEREO_R)
return ch->prefader.stereo_in->r;
}
break;
case PORT_OWNER_TYPE_SAMPLE_PROCESSOR:
if (id->flags & PORT_FLAG_STEREO_L)
return SAMPLE_PROCESSOR->stereo_out->l;
@ -357,6 +380,12 @@ port_get_all ( @@ -357,6 +380,12 @@ port_get_all (
_ADD (ch->fader.stereo_out->l);
_ADD (ch->fader.stereo_out->r);
/* add prefader ports */
_ADD (ch->prefader.stereo_in->l);
_ADD (ch->prefader.stereo_in->r);
_ADD (ch->prefader.stereo_out->l);
_ADD (ch->prefader.stereo_out->r);
#define ADD_PLUGIN_PORTS \
if (!pl) \
continue; \
@ -468,6 +497,23 @@ port_set_owner_fader ( @@ -468,6 +497,23 @@ port_set_owner_fader (
PORT_OWNER_TYPE_FADER;
}
/**
* Sets the owner fader & its ID.
*/
void
port_set_owner_prefader (
Port * port,
PassthroughProcessor * fader)
{
g_warn_if_fail (port && fader);
port->track = fader->channel->track;
port->identifier.track_pos =
fader->channel->track->pos;
port->identifier.owner_type =
PORT_OWNER_TYPE_PREFADER;
}
/**
*/
/*void*/

69
src/audio/routing.c

@ -34,6 +34,7 @@ @@ -34,6 +34,7 @@
#include "audio/midi.h"
#include "audio/modulator.h"
#include "audio/pan.h"
#include "audio/passthrough_processor.h"
#include "audio/port.h"
#include "audio/routing.h"
#include "audio/track.h"
@ -159,6 +160,12 @@ get_node_name ( @@ -159,6 +160,12 @@ get_node_name (
"%s Fader",
node->fader->channel->track->name);
break;
case ROUTE_NODE_TYPE_PREFADER:
return
g_strdup_printf (
"%s Pre-Fader",
node->prefader->channel->track->name);
break;
case ROUTE_NODE_TYPE_SAMPLE_PROCESSOR:
return
g_strdup ("Sample Processor");
@ -293,6 +300,11 @@ node_process ( @@ -293,6 +300,11 @@ node_process (
fader_process (
node->fader, local_offset, nframes);
}
else if (node->type == ROUTE_NODE_TYPE_PREFADER)
{
passthrough_processor_process (
node->prefader, local_offset, nframes);
}
else if (node->type ==
ROUTE_NODE_TYPE_SAMPLE_PROCESSOR)
{
@ -888,6 +900,22 @@ find_node_from_fader ( @@ -888,6 +900,22 @@ find_node_from_fader (
return NULL;
}
static GraphNode *
find_node_from_prefader (
Graph * graph,
PassthroughProcessor * prefader)
{
GraphNode * node;
for (int i = 0; i < graph->n_graph_nodes; i++)
{
node = graph->graph_nodes[i];
if (node->type == ROUTE_NODE_TYPE_PREFADER &&
node->prefader == prefader)
return node;
}
return NULL;
}
static GraphNode *
find_node_from_sample_processor (
Graph * graph,
@ -923,6 +951,8 @@ graph_node_new ( @@ -923,6 +951,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_PREFADER)
node->prefader = (PassthroughProcessor *) data;
else if (type ==
ROUTE_NODE_TYPE_SAMPLE_PROCESSOR)
node->sample_processor =
@ -1199,7 +1229,8 @@ add_port ( @@ -1199,7 +1229,8 @@ add_port (
Graph * self,
Port * port)
{
PortOwnerType owner = port->identifier.owner_type;
PortOwnerType owner =
port->identifier.owner_type;
/*add_port_node (self, port);*/
if (port->num_dests == 0 &&
@ -1216,7 +1247,8 @@ add_port ( @@ -1216,7 +1247,8 @@ add_port (
else if (port->num_dests == 0 &&
port->num_srcs == 0 &&
owner != PORT_OWNER_TYPE_PLUGIN &&
owner != PORT_OWNER_TYPE_FADER)
owner != PORT_OWNER_TYPE_FADER &&
owner != PORT_OWNER_TYPE_PREFADER)
{
}
else if (port->num_srcs == 0 &&
@ -1224,6 +1256,8 @@ add_port ( @@ -1224,6 +1256,8 @@ add_port (
port->identifier.flow == FLOW_OUTPUT) &&
!(owner == PORT_OWNER_TYPE_FADER &&
port->identifier.flow == FLOW_OUTPUT) &&
!(owner == PORT_OWNER_TYPE_PREFADER &&
port->identifier.flow == FLOW_OUTPUT) &&
!(owner ==
PORT_OWNER_TYPE_SAMPLE_PROCESSOR &&
port->identifier.flow == FLOW_OUTPUT))
@ -1237,6 +1271,9 @@ add_port ( @@ -1237,6 +1271,9 @@ add_port (
!(owner == PORT_OWNER_TYPE_FADER &&
port->identifier.flow ==
FLOW_INPUT) &&
!(owner == PORT_OWNER_TYPE_PREFADER &&
port->identifier.flow ==
FLOW_INPUT) &&
!(owner ==
PORT_OWNER_TYPE_SAMPLE_PROCESSOR &&
port->identifier.flow == FLOW_INPUT))
@ -1366,6 +1403,11 @@ graph_new ( @@ -1366,6 +1403,11 @@ graph_new (
self, ROUTE_NODE_TYPE_FADER,
&tr->channel->fader);
/* add the prefader */
graph_add_node ( \
self, ROUTE_NODE_TYPE_PREFADER,
&tr->channel->prefader);
#define ADD_PLUGIN \
if (!pl || pl->deleting) \
continue; \
@ -1441,6 +1483,7 @@ graph_new ( @@ -1441,6 +1483,7 @@ graph_new (
node_connect (node, node2);
Fader * fader;
PassthroughProcessor * prefader;
for (int i = 0; i < TRACKLIST->num_tracks; i++)
{
tr = TRACKLIST->tracks[i];
@ -1448,6 +1491,7 @@ graph_new ( @@ -1448,6 +1491,7 @@ graph_new (
continue;
fader = &tr->channel->fader;
prefader = &tr->channel->prefader;
/* connect the fader */
node =
@ -1470,6 +1514,27 @@ graph_new ( @@ -1470,6 +1514,27 @@ graph_new (
find_node_from_port (self, port);
node_connect (node, node2);
/* connect the prefader */
node =
find_node_from_prefader (
self, prefader);
port = prefader->stereo_in->l;
node2 =
find_node_from_port (self, port);
node_connect (node2, node);
port = prefader->stereo_in->r;
node2 =
find_node_from_port (self, port);
node_connect (node2, node);
port = prefader->stereo_out->l;
node2 =
find_node_from_port (self, port);
node_connect (node, node2);
port = prefader->stereo_out->r;
node2 =
find_node_from_port (self, port);
node_connect (node, node2);
#define CONNECT_PLUGIN \
if (!pl || pl->deleting) \
continue; \

61
src/gui/widgets/inspector_plugin.c

@ -40,62 +40,46 @@ inspector_plugin_widget_show ( @@ -40,62 +40,46 @@ inspector_plugin_widget_show (
{
Plugin * pl = ms->plugins[0];
ports_expander_widget_setup (
ports_expander_widget_setup_plugin (
self->ctrl_ins,
FLOW_INPUT,
TYPE_CONTROL,
PORT_OWNER_TYPE_PLUGIN,
pl,
NULL);
ports_expander_widget_setup (
pl);
ports_expander_widget_setup_plugin (
self->ctrl_outs,
FLOW_OUTPUT,
TYPE_CONTROL,
PORT_OWNER_TYPE_PLUGIN,
pl,
NULL);
ports_expander_widget_setup (
pl);
ports_expander_widget_setup_plugin (
self->midi_ins,
FLOW_INPUT,
TYPE_EVENT,
PORT_OWNER_TYPE_PLUGIN,
pl,
NULL);
ports_expander_widget_setup (
pl);
ports_expander_widget_setup_plugin (
self->midi_outs,
FLOW_OUTPUT,
TYPE_EVENT,
PORT_OWNER_TYPE_PLUGIN,
pl,
NULL);
ports_expander_widget_setup (
pl);
ports_expander_widget_setup_plugin (
self->audio_ins,
FLOW_INPUT,
TYPE_AUDIO,
PORT_OWNER_TYPE_PLUGIN,
pl,
NULL);
ports_expander_widget_setup (
pl);
ports_expander_widget_setup_plugin (
self->audio_outs,
FLOW_OUTPUT,
TYPE_AUDIO,
PORT_OWNER_TYPE_PLUGIN,
pl,
NULL);
ports_expander_widget_setup (
pl);
ports_expander_widget_setup_plugin (
self->cv_ins,
FLOW_INPUT,
TYPE_CV,
PORT_OWNER_TYPE_PLUGIN,
pl,
NULL);
ports_expander_widget_setup (
pl);
ports_expander_widget_setup_plugin (
self->cv_outs,
FLOW_OUTPUT,
TYPE_CV,
PORT_OWNER_TYPE_PLUGIN,
pl,
NULL);
pl);
}
}
@ -108,10 +92,13 @@ inspector_plugin_widget_class_init ( @@ -108,10 +92,13 @@ inspector_plugin_widget_class_init (
resources_set_class_template (
klass, "inspector_plugin.ui");
gtk_widget_class_bind_template_child (
GTK_WIDGET_CLASS (klass),
InspectorPluginWidget,
ctrl_ins);
#define BIND_CHILD(child) \
gtk_widget_class_bind_template_child ( \
GTK_WIDGET_CLASS (klass), \
InspectorPluginWidget, \
child);
BIND_CHILD (ctrl_ins);
gtk_widget_class_bind_template_child (
GTK_WIDGET_CLASS (klass),
InspectorPluginWidget,
@ -140,6 +127,8 @@ inspector_plugin_widget_class_init ( @@ -140,6 +127,8 @@ inspector_plugin_widget_class_init (
GTK_WIDGET_CLASS (klass),
InspectorPluginWidget,
cv_outs);
#undef BIND_CHILD
}
static void

13
src/gui/widgets/inspector_track.c

@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
#include "gui/backend/tracklist_selections.h"
#include "gui/widgets/inspector_track.h"
#include "gui/widgets/instrument_track_info_expander.h"
#include "gui/widgets/ports_expander.h"
#include "project.h"
#include "utils/resources.h"
@ -38,13 +39,21 @@ inspector_track_widget_show_tracks ( @@ -38,13 +39,21 @@ inspector_track_widget_show_tracks (
TracklistSelections * tls)
{
/* show info for first track */
Track * track;
if (tls->num_tracks > 0)
{
Track * track = tls->tracks[0];
track = tls->tracks[0];
instrument_track_info_expander_widget_setup (
self->instrument_track_info,
track);
ports_expander_widget_setup_sends (
self->prefader_sends,
track, 1);
ports_expander_widget_setup_sends (
self->postfader_sends,
track, 0);
}
}
@ -64,6 +73,8 @@ inspector_track_widget_class_init ( @@ -64,6 +73,8 @@ inspector_track_widget_class_init (
child);
BIND_CHILD (instrument_track_info);
BIND_CHILD (prefader_sends);
BIND_CHILD (postfader_sends);
#undef BIND_CHILD
}

8
src/gui/widgets/port_connections_button.c

@ -21,6 +21,8 @@ @@ -21,6 +21,8 @@
#include "gui/widgets/port_connections_button.h"