2
* Copyright © 2021 Pojar Gheorghe–Ioan <geoubuntu@gmail.com>
4
* This program is free software; you can redistribute it and/or
5
* modify it under the tedecay of the GNU General Public License as
6
* published by the Free Software Foundation; either version 2 of
7
* the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20
#include <glib/gi18n.h>
23
#include "builder_utils.h"
27
#define REDRAW_TIMEOUT 1
29
#define NOTIFICATION_TIMEOUT 5
31
static GtkWidget *window;
32
static GtkWidget *record_notification_revealer;
33
static GtkWidget *drawing_area;
34
static GtkWidget *name_entry;
35
static GtkWidget *size_label;
36
static GtkWidget *duration_label;
38
static guint notification_timeout_id;
41
cancel_idle (Recording *recording)
43
recording_window_data_free (recording);
44
recording_stop (recording);
46
return G_SOURCE_REMOVE;
50
redraw_recording_window (Recording *recording)
54
if (recording->error != NULL)
56
RecordingWindowData *data = (RecordingWindowData *) recording->window_data;
58
data->redraw_recording_window_timeout_id = 0;
59
return G_SOURCE_REMOVE;
62
text = g_format_size_full (recording->file_size, G_FORMAT_SIZE_LONG_FORMAT);
63
gtk_label_set_text (GTK_LABEL (size_label), text);
66
text = recording_time_to_string (recording->secs);
67
gtk_label_set_text (GTK_LABEL (duration_label), text);
70
return G_SOURCE_CONTINUE;
74
notification_close (gpointer user_data)
76
g_clear_handle_id (¬ification_timeout_id, g_source_remove);
77
gtk_revealer_set_reveal_child (GTK_REVEALER (record_notification_revealer), FALSE);
79
return G_SOURCE_REMOVE;
83
on_record_notification_enter_notify_event (GtkWidget *widget,
87
g_clear_handle_id (¬ification_timeout_id, g_source_remove);
89
return GDK_EVENT_PROPAGATE;
93
on_record_notification_leave_notify_event (GtkWidget *widget,
97
g_clear_handle_id (¬ification_timeout_id, g_source_remove);
98
notification_timeout_id = g_timeout_add_seconds (NOTIFICATION_TIMEOUT, G_SOURCE_FUNC (notification_close), NULL);
100
return GDK_EVENT_PROPAGATE;
104
on_record_notification_details_button_clicked (GtkButton *button,
109
g_clear_handle_id (¬ification_timeout_id, g_source_remove);
110
gtk_revealer_set_reveal_child (GTK_REVEALER (record_notification_revealer), FALSE);
112
dialog = gtk_message_dialog_new (GTK_WINDOW (window),
114
GTK_DIALOG_DESTROY_WITH_PARENT,
117
_("Encoding profile is missing"));
119
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
120
"%s", _("An encoding profile is missing, the incoming data is captured as a raw audio file, but the file may take up a lot of disk space."));
122
gtk_dialog_run (GTK_DIALOG (dialog));
123
gtk_widget_destroy (dialog);
127
on_record_notification_close_button_clicked (GtkButton *button,
130
g_clear_handle_id (¬ification_timeout_id, g_source_remove);
131
gtk_revealer_set_reveal_child (GTK_REVEALER (record_notification_revealer), FALSE);
135
on_record_notification_revealer_unrealize (GtkWidget *widget,
138
g_clear_handle_id (¬ification_timeout_id, g_source_remove);
142
run_recording_window (Recording *recording)
144
RecordingWindowData *data = g_new0 (RecordingWindowData, 1);
146
recording->window_data = data;
148
if (recording->error == NULL)
150
g_autofree gchar *markup = NULL;
152
data->window = window;
153
data->drawing_area = drawing_area;
154
data->name_entry = name_entry;
155
data->redraw_recording_window_timeout_id = g_timeout_add_seconds (REDRAW_TIMEOUT,
156
G_SOURCE_FUNC (redraw_recording_window),
159
markup = g_strdup_printf (_("Recording from station %s"), recording->station);
160
data->inhibit_cookie = gtk_application_inhibit (GTK_APPLICATION (g_application_get_default ()),
161
GTK_WINDOW (data->window),
162
GTK_APPLICATION_INHIBIT_IDLE,
165
gtk_widget_show (data->window);
167
if (recording->profile == NULL)
169
gtk_revealer_set_reveal_child (GTK_REVEALER (record_notification_revealer), TRUE);
170
notification_timeout_id = g_timeout_add_seconds (NOTIFICATION_TIMEOUT, G_SOURCE_FUNC (notification_close), NULL);
175
if (g_error_matches (recording->error, RECORDING_ERROR, RECORDING_ERROR_MISSING_PLUGIN))
177
g_idle_add (G_SOURCE_FUNC (cancel_idle), recording);
183
on_stop_recording_button_clicked (GtkButton *button,
186
Recording *recording = (Recording *) user_data;
188
g_idle_add (G_SOURCE_FUNC (cancel_idle), recording);
192
on_recording_drawing_area_draw (GtkWidget *widget,
196
Recording *recording = (Recording *) user_data;
197
GtkStyleContext *context;
199
int width, height, middle;
201
gdouble peak0, peak1, decay0, decay1;
203
if (!gtk_widget_get_realized (widget))
208
context = gtk_widget_get_style_context (widget);
209
width = gtk_widget_get_allocated_width (widget);
210
height = gtk_widget_get_allocated_height (widget);
212
gtk_render_background (context, cr, 0, 0, width, height);
215
scl = middle / (-MIN_LEVEL_VALUE);
217
peak0 = recording->peak[0] * scl;
218
peak1 = recording->peak[1] * scl;
219
decay0 = recording->decay[0] * scl;
220
decay1 = recording->decay[1] * scl;
222
gtk_style_context_get_color (context, gtk_style_context_get_state (context), &color);
224
cairo_set_source_rgb (cr, color.red, color.green, color.blue);
225
cairo_rectangle (cr, middle - decay0, 0, 2, height);
227
cairo_rectangle (cr, (middle - 1) + decay1, 0, 2, height);
230
cairo_set_source_rgba (cr, color.red, color.green, color.blue, 0.2);
231
cairo_rectangle (cr, middle - peak0, 0, peak0 + peak1, height);
238
on_recording_window_delete_event (GtkWidget *widget,
242
Recording *recording = (Recording *) user_data;
244
g_idle_add (G_SOURCE_FUNC (cancel_idle), recording);
246
return GDK_EVENT_STOP;
250
on_recording_details_expander_activate (GtkExpander *expander,
253
Recording *recording = (Recording *) user_data;
256
gtk_entry_set_text (GTK_ENTRY ((name_entry)), recording->display_name);
257
text_length = (guint) gtk_entry_get_text_length (GTK_ENTRY ((name_entry)));
258
if (text_length == 0)
263
gtk_editable_select_region (GTK_EDITABLE (name_entry), 0, -1);
265
gtk_entry_grab_focus_without_selecting (GTK_ENTRY ((name_entry)));
269
recording_name_entry_restore_original_name (GtkWidget *widget,
272
Recording *recording = (Recording *) user_data;
273
g_autofree char *displayed_name = NULL;
275
displayed_name = gtk_editable_get_chars (GTK_EDITABLE (widget), 0, -1);
277
if (strcmp (displayed_name, recording->display_name) != 0)
279
gtk_entry_set_text (GTK_ENTRY (widget), recording->display_name);
282
gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
286
on_recording_name_entry_activate (GtkEntry *entry,
289
Recording *recording = (Recording *) user_data;
290
g_autofree char *new_name = NULL;
292
new_name = g_strstrip (gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1));
293
/* Special case: silently revert text if new text is empty */
294
if (strlen (new_name) == 0)
296
recording_name_entry_restore_original_name (GTK_WIDGET (entry), recording);
300
/* Do not rename if not changed since we read the display name.
301
* This is needed so that we do not save the display name to the
302
* file when nothing is changed */
303
if (strcmp (new_name, recording->display_name) != 0)
305
g_free (recording->display_name);
306
recording->display_name = g_strdup (new_name);
308
recording_output_file_rename (recording);
312
gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
316
on_recording_name_entry_undo (GtkWidget *widget,
319
Recording *recording = (Recording *) user_data;
321
recording_name_entry_restore_original_name (widget, recording);
323
return GDK_EVENT_STOP;
327
on_recording_name_entry_event (GtkWidget *widget,
331
Recording *recording = (Recording *) user_data;
333
GdkModifierType state;
335
if (gdk_event_get_event_type (event) != GDK_KEY_PRESS)
337
return GDK_EVENT_PROPAGATE;
340
if (G_UNLIKELY (!gdk_event_get_keyval (event, &keyval)))
342
g_return_val_if_reached (GDK_EVENT_PROPAGATE);
344
if (G_UNLIKELY (!gdk_event_get_state (event, &state)))
346
g_return_val_if_reached (GDK_EVENT_PROPAGATE);
349
if (keyval == GDK_KEY_z && (state & GDK_CONTROL_MASK) != 0)
351
return on_recording_name_entry_undo (widget, recording);
354
return GDK_EVENT_PROPAGATE;
358
on_recording_location_label_realize (GtkWidget *widget,
361
Recording *recording = (Recording *) user_data;
362
g_autoptr (GFile) parent = NULL;
363
g_autofree char *name = NULL;
365
if (recording->file == NULL)
370
parent = g_file_get_parent (recording->file);
371
name = g_file_get_parse_name (parent);
373
gtk_label_set_text (GTK_LABEL (widget), name);
377
recording_window (Recording *recording)
379
g_autoptr (GtkBuilder) builder = NULL;
381
g_autofree gchar *markup = NULL;
383
builder = builder_load (GNOME_RADIO_UI_RESOURCE_PATH "record.ui", recording);
385
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
387
widget = GTK_WIDGET (gtk_builder_get_object (builder, "title_label"));
389
markup = g_markup_printf_escaped (_("Recording from station %s"), recording->station);
390
gtk_label_set_markup (GTK_LABEL (widget), markup);
392
record_notification_revealer = GTK_WIDGET (gtk_builder_get_object (builder, "record_notification_revealer"));
394
drawing_area = GTK_WIDGET (gtk_builder_get_object (builder, "drawing_area"));
396
name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry"));
398
size_label = GTK_WIDGET (gtk_builder_get_object (builder, "size_label"));
400
duration_label = GTK_WIDGET (gtk_builder_get_object (builder, "duration_label"));