1 /*
2 * Copyright (C) 2019-2021 Alexandros Theodotou <alex at zrythm dot org>
3 *
4 * This file is part of Zrythm
5 *
6 * Zrythm is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Zrythm is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "audio/automation_track.h"
21 #include "audio/channel_track.h"
22 #include "audio/port_connections_manager.h"
23 #include "gui/widgets/port_connection_row.h"
24 #include "gui/widgets/inspector_port.h"
25 #include "gui/widgets/port_connections_popover.h"
26 #include "gui/widgets/port_selector_popover.h"
27 #include "plugins/plugin.h"
28 #include "project.h"
29 #include "utils/flags.h"
30 #include "utils/gtk.h"
31 #include "utils/resources.h"
32
33 #include <gtk/gtk.h>
34 #include <glib/gi18n.h>
35
G_DEFINE_TYPE(PortConnectionsPopoverWidget,port_connections_popover_widget,GTK_TYPE_POPOVER)36 G_DEFINE_TYPE (
37 PortConnectionsPopoverWidget,
38 port_connections_popover_widget,
39 GTK_TYPE_POPOVER)
40
41 static void
42 on_add_clicked (
43 GtkButton * btn,
44 PortConnectionsPopoverWidget * self)
45 {
46 PortSelectorPopoverWidget * psp =
47 port_selector_popover_widget_new (
48 self, self->port);
49 gtk_popover_set_relative_to (
50 GTK_POPOVER (psp), GTK_WIDGET (btn));
51 gtk_popover_set_position (
52 GTK_POPOVER (psp), GTK_POS_RIGHT);
53 gtk_widget_show_all (GTK_WIDGET (psp));
54 }
55
56 void
port_connections_popover_widget_refresh(PortConnectionsPopoverWidget * self)57 port_connections_popover_widget_refresh (
58 PortConnectionsPopoverWidget * self)
59 {
60 z_gtk_container_destroy_all_children (
61 GTK_CONTAINER (self->ports_box));
62
63 /* set title and add ports */
64 if (self->port->id.flow == FLOW_INPUT)
65 {
66 if (GTK_IS_LABEL (self->title))
67 {
68 gtk_label_set_text (
69 self->title, _("INPUTS"));
70 }
71
72 GPtrArray * srcs = g_ptr_array_new ();
73 int num_srcs =
74 port_connections_manager_get_sources_or_dests (
75 PORT_CONNECTIONS_MGR, srcs,
76 &self->port->id, true);
77 for (int i = 0; num_srcs; i++)
78 {
79 PortConnection * conn =
80 g_ptr_array_index (srcs, i);
81 if (!conn->locked)
82 {
83 PortConnectionRowWidget * pcr =
84 port_connection_row_widget_new (
85 self, conn, true);
86 gtk_container_add (
87 GTK_CONTAINER (self->ports_box),
88 GTK_WIDGET (pcr));
89 }
90 }
91 g_ptr_array_unref (srcs);
92 }
93 else if (self->port->id.flow ==
94 FLOW_OUTPUT)
95 {
96 if (GTK_IS_LABEL (self->title))
97 {
98 gtk_label_set_text (
99 self->title, _("OUTPUTS"));
100 }
101
102 GPtrArray * dests = g_ptr_array_new ();
103 int num_dests =
104 port_connections_manager_get_sources_or_dests (
105 PORT_CONNECTIONS_MGR, dests,
106 &self->port->id, false);
107 for (int i = 0; i < num_dests; i++)
108 {
109 PortConnection * conn =
110 g_ptr_array_index (dests, i);
111 if (!conn->locked)
112 {
113 PortConnectionRowWidget * pcr =
114 port_connection_row_widget_new (
115 self, conn, false);
116 gtk_container_add (
117 GTK_CONTAINER (self->ports_box),
118 GTK_WIDGET (pcr));
119 }
120 }
121 g_ptr_array_unref (dests);
122 }
123 }
124
125 /**
126 * Creates the popover.
127 *
128 * @param owner Owner widget to pop up at.
129 * @param port Owner port.
130 */
131 PortConnectionsPopoverWidget *
port_connections_popover_widget_new(GtkWidget * owner,Port * port)132 port_connections_popover_widget_new (
133 GtkWidget * owner,
134 Port * port)
135 {
136 g_return_val_if_fail (
137 GTK_IS_WIDGET (owner) && IS_PORT (port), NULL);
138
139 PortConnectionsPopoverWidget * self =
140 g_object_new (
141 PORT_CONNECTIONS_POPOVER_WIDGET_TYPE, NULL);
142
143 self->port = port;
144 gtk_popover_set_relative_to (
145 GTK_POPOVER (self),
146 GTK_WIDGET (owner));
147
148 port_connections_popover_widget_refresh (self);
149
150 return self;
151 }
152
153 static void
finalize(PortConnectionsPopoverWidget * self)154 finalize (
155 PortConnectionsPopoverWidget * self)
156 {
157 G_OBJECT_CLASS (
158 port_connections_popover_widget_parent_class)->
159 finalize (G_OBJECT (self));
160 }
161
162 static void
port_connections_popover_widget_class_init(PortConnectionsPopoverWidgetClass * _klass)163 port_connections_popover_widget_class_init (
164 PortConnectionsPopoverWidgetClass * _klass)
165 {
166 GObjectClass * oklass = G_OBJECT_CLASS (_klass);
167 oklass->finalize =
168 (GObjectFinalizeFunc) finalize;
169 }
170
171 static void
port_connections_popover_widget_init(PortConnectionsPopoverWidget * self)172 port_connections_popover_widget_init (
173 PortConnectionsPopoverWidget * self)
174 {
175 /* create all */
176 self->main_box =
177 GTK_BOX (
178 gtk_box_new (GTK_ORIENTATION_VERTICAL, 2));
179 gtk_widget_set_visible (
180 GTK_WIDGET (self->main_box), 1);
181 self->title =
182 GTK_LABEL (gtk_label_new (""));
183 gtk_widget_set_visible (
184 GTK_WIDGET (self->title), 1);
185 self->ports_box =
186 GTK_BOX (
187 gtk_box_new (GTK_ORIENTATION_VERTICAL, 1));
188 gtk_widget_set_visible (
189 GTK_WIDGET (self->ports_box), 1);
190
191 self->add =
192 GTK_BUTTON (gtk_button_new ());
193 gtk_widget_set_visible (
194 GTK_WIDGET (self->add), true);
195 GtkWidget * btn_box =
196 gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
197 gtk_widget_set_visible (btn_box, true);
198 GtkWidget * img =
199 gtk_image_new_from_icon_name (
200 "add", GTK_ICON_SIZE_BUTTON);
201 gtk_widget_set_visible (img, true);
202 gtk_box_pack_start (
203 GTK_BOX (btn_box), img,
204 F_NO_EXPAND, F_NO_FILL, 0);
205 GtkWidget * lbl =
206 gtk_label_new (_("Add"));
207 gtk_widget_set_visible (lbl, 1);
208 gtk_box_pack_end (
209 GTK_BOX (btn_box), lbl,
210 1, 1, 0);
211 gtk_container_add (
212 GTK_CONTAINER (self->add),
213 btn_box);
214 g_signal_connect (
215 G_OBJECT (self->add), "clicked",
216 G_CALLBACK (on_add_clicked), self);
217
218 GtkWidget * separator =
219 gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
220 gtk_widget_set_visible (separator, 1);
221
222 /* add to each other */
223 gtk_box_pack_start (
224 self->main_box, GTK_WIDGET (self->title),
225 F_NO_EXPAND, F_NO_FILL, 0);
226 gtk_box_pack_start (
227 self->main_box, separator,
228 F_NO_EXPAND, F_NO_FILL, 0);
229 gtk_box_pack_start (
230 self->main_box, GTK_WIDGET (self->ports_box),
231 F_NO_EXPAND, F_NO_FILL, 0);
232 gtk_box_pack_start (
233 self->main_box, GTK_WIDGET (self->add),
234 F_NO_EXPAND, F_NO_FILL, 0);
235
236 /* add to popover */
237 gtk_container_add (
238 GTK_CONTAINER (self),
239 GTK_WIDGET (self->main_box));
240 /*g_object_ref (self);*/
241 }
242