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 "actions/arranger_selections.h"
21 #include "audio/quantize_options.h"
22 #include "gui/widgets/bar_slider.h"
23 #include "gui/widgets/digital_meter.h"
24 #include "gui/widgets/dialogs/quantize_dialog.h"
25 #include "project.h"
26 #include "utils/error.h"
27 #include "utils/io.h"
28 #include "utils/resources.h"
29 #include "zrythm_app.h"
30 
31 #include <gtk/gtk.h>
32 #include <glib/gi18n.h>
33 
G_DEFINE_TYPE(QuantizeDialogWidget,quantize_dialog_widget,GTK_TYPE_DIALOG)34 G_DEFINE_TYPE (
35   QuantizeDialogWidget,
36   quantize_dialog_widget,
37   GTK_TYPE_DIALOG)
38 
39 static void
40 on_adjust_end_toggled (
41   GtkToggleButton * toggle,
42   QuantizeDialogWidget * self)
43 {
44   self->opts->adj_end =
45     gtk_toggle_button_get_active (toggle);
46 }
47 
48 static void
on_adjust_start_toggled(GtkToggleButton * toggle,QuantizeDialogWidget * self)49 on_adjust_start_toggled (
50   GtkToggleButton * toggle,
51   QuantizeDialogWidget * self)
52 {
53   self->opts->adj_start =
54     gtk_toggle_button_get_active (toggle);
55 }
56 
57 static void
on_cancel_clicked(GtkButton * btn,QuantizeDialogWidget * self)58 on_cancel_clicked (
59   GtkButton * btn,
60   QuantizeDialogWidget * self)
61 {
62   gtk_window_close (GTK_WINDOW (self));
63 }
64 
65 static void
on_quantize_clicked(GtkButton * btn,QuantizeDialogWidget * self)66 on_quantize_clicked (
67   GtkButton * btn,
68   QuantizeDialogWidget * self)
69 {
70   if (QUANTIZE_OPTIONS_IS_EDITOR (self->opts))
71     {
72       ArrangerSelections * sel =
73         clip_editor_get_arranger_selections (
74           CLIP_EDITOR);
75       g_return_if_fail (sel);
76 
77       GError * err = NULL;
78       bool ret =
79         arranger_selections_action_perform_quantize (
80           sel, self->opts, &err);
81       if (!ret)
82         {
83           HANDLE_ERROR (
84             err, "%s",
85             _("Failed to quantize editor "
86             "selections"));
87         }
88     }
89   else if (QUANTIZE_OPTIONS_IS_TIMELINE (self->opts))
90     {
91       GError * err = NULL;
92       bool ret =
93         arranger_selections_action_perform_quantize (
94           (ArrangerSelections *) TL_SELECTIONS,
95           self->opts, &err);
96       if (!ret)
97         {
98           HANDLE_ERROR (
99             err, "%s",
100             _("Failed to quantize timeline "
101             "selections"));
102         }
103     }
104 }
105 
106 /**
107  * Creates a new quantize dialog.
108  */
109 QuantizeDialogWidget *
quantize_dialog_widget_new(QuantizeOptions * opts)110 quantize_dialog_widget_new (
111   QuantizeOptions * opts)
112 {
113   QuantizeDialogWidget * self =
114     g_object_new (QUANTIZE_DIALOG_WIDGET_TYPE, NULL);
115 
116   self->opts = opts;
117 
118   gtk_toggle_button_set_active (
119     self->adjust_start, opts->adj_start);
120   gtk_toggle_button_set_active (
121     self->adjust_end, opts->adj_end);
122 
123   g_signal_connect (
124     G_OBJECT (self->adjust_start), "toggled",
125     G_CALLBACK (on_adjust_start_toggled), self);
126   g_signal_connect (
127     G_OBJECT (self->adjust_end), "toggled",
128     G_CALLBACK (on_adjust_end_toggled), self);
129 
130   self->note_length =
131     digital_meter_widget_new (
132       DIGITAL_METER_TYPE_NOTE_LENGTH,
133       &opts->note_length,
134       &opts->note_type,
135       _("note length"));
136   gtk_container_add (
137     GTK_CONTAINER (self->note_length_box),
138     GTK_WIDGET (self->note_length));
139   self->note_type =
140     digital_meter_widget_new (
141       DIGITAL_METER_TYPE_NOTE_TYPE,
142       &opts->note_length,
143       &opts->note_type,
144       _("note type"));
145   gtk_container_add (
146     GTK_CONTAINER (self->note_type_box),
147     GTK_WIDGET (self->note_type));
148 
149   int w = 100, h = -1;
150   self->amount =
151     bar_slider_widget_new (
152       quantize_options_get_amount,
153       quantize_options_set_amount,
154       opts, 0, 100, w, h, 0, 0,
155       UI_DRAG_MODE_CURSOR, "%");
156   gtk_container_add (
157     GTK_CONTAINER (self->amount_box),
158     GTK_WIDGET (self->amount));
159   self->swing =
160     bar_slider_widget_new (
161       quantize_options_get_swing,
162       quantize_options_set_swing,
163       opts, 0, 100, w, h, 0, 0,
164       UI_DRAG_MODE_CURSOR, "%");
165   gtk_container_add (
166     GTK_CONTAINER (self->swing_box),
167     GTK_WIDGET (self->swing));
168   self->randomization =
169     bar_slider_widget_new (
170       quantize_options_get_randomization,
171       quantize_options_set_randomization,
172       opts, 0.f, 100.f, w, h, 0, 0,
173       UI_DRAG_MODE_CURSOR, " ticks");
174   gtk_container_add (
175     GTK_CONTAINER (self->randomization_box),
176     GTK_WIDGET (self->randomization));
177 
178   return self;
179 }
180 
181 static void
quantize_dialog_widget_class_init(QuantizeDialogWidgetClass * _klass)182 quantize_dialog_widget_class_init (
183   QuantizeDialogWidgetClass * _klass)
184 {
185   GtkWidgetClass * klass = GTK_WIDGET_CLASS (_klass);
186   resources_set_class_template (
187     klass, "quantize_dialog.ui");
188 
189 #define BIND_CHILD(x) \
190   gtk_widget_class_bind_template_child ( \
191     klass, \
192     QuantizeDialogWidget, \
193     x)
194 
195   BIND_CHILD (cancel_btn);
196   BIND_CHILD (quantize_btn);
197   BIND_CHILD (adjust_start);
198   BIND_CHILD (adjust_end);
199   BIND_CHILD (note_length_box);
200   BIND_CHILD (note_type_box);
201   BIND_CHILD (amount_box);
202   BIND_CHILD (swing_box);
203   BIND_CHILD (randomization_box);
204 
205   gtk_widget_class_bind_template_callback (
206     klass,
207     on_cancel_clicked);
208   gtk_widget_class_bind_template_callback (
209     klass,
210     on_quantize_clicked);
211 }
212 
213 static void
quantize_dialog_widget_init(QuantizeDialogWidget * self)214 quantize_dialog_widget_init (
215   QuantizeDialogWidget * self)
216 {
217   gtk_widget_init_template (GTK_WIDGET (self));
218 }
219