1 /*
2     Waveform seekbar plugin for the DeaDBeeF audio player
3 
4     Copyright (C) 2014 Christian Boxdörfer <christian.boxdoerfer@posteo.de>
5 
6     Based on sndfile-tools waveform by Erik de Castro Lopo.
7         waveform.c - v1.04
8         Copyright (C) 2007-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
9         Copyright (C) 2012 Robin Gareus <robin@gareus.org>
10         Copyright (C) 2013 driedfruit <driedfruit@mindloop.net>
11 
12     This program is free software; you can redistribute it and/or
13     modify it under the terms of the GNU General Public License
14     as published by the Free Software Foundation; either version 2
15     of the License, or (at your option) any later version.
16 
17     This program is distributed in the hope that it will be useful,
18     but WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20     GNU General Public License for more details.
21 
22     You should have received a copy of the GNU General Public License
23     along with this program; if not, write to the Free Software
24     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
25 */
26 
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <stdlib.h>
30 #include <fcntl.h>
31 #include <gtk/gtk.h>
32 
33 #include <deadbeef/deadbeef.h>
34 
35 #include "config.h"
36 #include "waveform.h"
37 #include "config_dialog.h"
38 
39 #if !GTK_CHECK_VERSION(2,14,0)
40 #define gtk_widget_get_window(widget) ((widget)->window)
41 #define gtk_dialog_get_content_area(dialog) (dialog->vbox)
42 #define gtk_dialog_get_action_area(dialog) (dialog->action_area)
43 #endif
44 
45 #if !GTK_CHECK_VERSION(2,18,0)
46 void
gtk_widget_get_allocation(GtkWidget * widget,GtkAllocation * allocation)47 gtk_widget_get_allocation (GtkWidget *widget, GtkAllocation *allocation) {
48     (allocation)->x = widget->allocation.x;
49     (allocation)->y = widget->allocation.y;
50     (allocation)->width = widget->allocation.width;
51     (allocation)->height = widget->allocation.height;
52 }
53 #define gtk_widget_set_can_default(widget, candefault) {if (candefault) GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_DEFAULT); else GTK_WIDGET_UNSET_FLAGS(widget, GTK_CAN_DEFAULT);}
54 #endif
55 
56 #pragma GCC diagnostic push
57 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
58 void
on_button_config(GtkMenuItem * menuitem,gpointer user_data)59 on_button_config (GtkMenuItem *menuitem, gpointer user_data)
60 {
61     GtkWidget *waveform_properties;
62     GtkWidget *config_dialog;
63     GtkWidget *vbox01;
64     GtkWidget *color_label;
65     GtkWidget *color_frame;
66     GtkWidget *color_table;
67     GtkWidget *color_background_label;
68     GtkWidget *background_color;
69     GtkWidget *color_waveform_label;
70     GtkWidget *foreground_color;
71     GtkWidget *color_rms_label;
72     GtkWidget *foreground_rms_color;
73     GtkWidget *color_progressbar_label;
74     GtkWidget *progressbar_color;
75     GtkWidget *downmix_to_mono;
76     GtkWidget *log_scale;
77     GtkWidget *display_rms;
78     GtkWidget *display_ruler;
79     GtkWidget *style_label;
80     GtkWidget *style_frame;
81     GtkWidget *vbox02;
82     GtkWidget *render_method_spikes;
83     GtkWidget *render_method_bars;
84     GtkWidget *shade_waveform;
85     GtkWidget *fill_waveform;
86     GtkWidget *soundcloud_style;
87     GtkWidget *dialog_action_area13;
88     GtkWidget *applybutton1;
89     GtkWidget *cancelbutton1;
90     GtkWidget *okbutton1;
91     waveform_properties = gtk_dialog_new ();
92     gtk_window_set_title (GTK_WINDOW (waveform_properties), "Waveform Properties");
93     gtk_window_set_type_hint (GTK_WINDOW (waveform_properties), GDK_WINDOW_TYPE_HINT_DIALOG);
94 
95     config_dialog = gtk_dialog_get_content_area (GTK_DIALOG (waveform_properties));
96     gtk_widget_show (config_dialog);
97 
98     vbox01 = gtk_vbox_new (FALSE, 8);
99     gtk_widget_show (vbox01);
100     gtk_box_pack_start (GTK_BOX (config_dialog), vbox01, FALSE, FALSE, 0);
101     gtk_container_set_border_width (GTK_CONTAINER (vbox01), 12);
102 
103     color_label = gtk_label_new (NULL);
104     gtk_label_set_markup (GTK_LABEL (color_label),"<b>Colors</b>");
105     gtk_widget_show (color_label);
106 
107     color_frame = gtk_frame_new ("Colors");
108     gtk_frame_set_label_widget ((GtkFrame *)color_frame, color_label);
109     gtk_frame_set_shadow_type ((GtkFrame *)color_frame, GTK_SHADOW_IN);
110     gtk_widget_show (color_frame);
111     gtk_box_pack_start (GTK_BOX (vbox01), color_frame, TRUE, FALSE, 0);
112 
113     color_table = gtk_table_new (2, 4, TRUE);
114     gtk_widget_show (color_table);
115     gtk_container_add (GTK_CONTAINER (color_frame), color_table);
116     gtk_table_set_col_spacings ((GtkTable *) color_table, 8);
117     gtk_container_set_border_width (GTK_CONTAINER (color_table), 6);
118 
119     color_background_label = gtk_label_new ("Background");
120     gtk_widget_show (color_background_label);
121     gtk_table_attach_defaults ((GtkTable *) color_table, color_background_label, 0,1,0,1);
122 
123     color_waveform_label = gtk_label_new ("Waveform");
124     gtk_widget_show (color_waveform_label);
125     gtk_table_attach_defaults ((GtkTable *) color_table, color_waveform_label, 1,2,0,1);
126 
127     color_rms_label = gtk_label_new ("RMS");
128     gtk_widget_show (color_rms_label);
129     gtk_table_attach_defaults ((GtkTable *) color_table, color_rms_label, 2,3,0,1);
130 
131     color_progressbar_label = gtk_label_new ("Progressbar");
132     gtk_widget_show (color_progressbar_label);
133     gtk_table_attach_defaults ((GtkTable *) color_table, color_progressbar_label, 3,4,0,1);
134 
135     background_color = gtk_color_button_new ();
136     gtk_color_button_set_use_alpha ((GtkColorButton *)background_color, TRUE);
137     gtk_widget_show (background_color);
138     gtk_table_attach_defaults ((GtkTable *) color_table, background_color, 0,1,1,2);
139 
140     foreground_color = gtk_color_button_new ();
141     gtk_color_button_set_use_alpha ((GtkColorButton *)foreground_color, TRUE);
142     gtk_widget_show (foreground_color);
143     gtk_table_attach_defaults ((GtkTable *) color_table, foreground_color, 1,2,1,2);
144 
145     foreground_rms_color = gtk_color_button_new ();
146     gtk_color_button_set_use_alpha ((GtkColorButton *)foreground_rms_color, TRUE);
147     gtk_widget_show (foreground_rms_color);
148     gtk_table_attach_defaults ((GtkTable *) color_table, foreground_rms_color, 2,3,1,2);
149 
150     progressbar_color = gtk_color_button_new ();
151     gtk_color_button_set_use_alpha ((GtkColorButton *)progressbar_color, TRUE);
152     gtk_widget_show (progressbar_color);
153     gtk_table_attach_defaults ((GtkTable *) color_table, progressbar_color, 3,4,1,2);
154 
155     style_label = gtk_label_new (NULL);
156     gtk_label_set_markup (GTK_LABEL (style_label),"<b>Style</b>");
157     gtk_widget_show (style_label);
158 
159     style_frame = gtk_frame_new ("Style");
160     gtk_frame_set_label_widget ((GtkFrame *)style_frame, style_label);
161     gtk_frame_set_shadow_type ((GtkFrame *)style_frame, GTK_SHADOW_IN);
162     gtk_widget_show (style_frame);
163     gtk_box_pack_start (GTK_BOX (vbox01), style_frame, FALSE, FALSE, 0);
164 
165     vbox02 = gtk_vbox_new (FALSE, 6);
166     gtk_widget_show (vbox02);
167     gtk_container_add (GTK_CONTAINER (style_frame), vbox02);
168 
169     render_method_spikes = gtk_radio_button_new_with_label (NULL, "Spikes");
170     gtk_widget_show (render_method_spikes);
171     gtk_box_pack_start (GTK_BOX (vbox02), render_method_spikes, TRUE, TRUE, 0);
172 
173     render_method_bars = gtk_radio_button_new_with_label_from_widget ((GtkRadioButton *)render_method_spikes, "Bars");
174     gtk_widget_show (render_method_bars);
175     gtk_box_pack_start (GTK_BOX (vbox02), render_method_bars, TRUE, TRUE, 0);
176 
177     fill_waveform = gtk_check_button_new_with_label ("Fill waveform");
178     gtk_widget_show (fill_waveform);
179     gtk_box_pack_start (GTK_BOX (vbox02), fill_waveform, TRUE, TRUE, 0);
180 
181     soundcloud_style = gtk_check_button_new_with_label ("Soundcloud style");
182     gtk_widget_show (soundcloud_style);
183     gtk_box_pack_start (GTK_BOX (vbox02), soundcloud_style, TRUE, TRUE, 0);
184 
185     shade_waveform = gtk_check_button_new_with_label ("Shade waveform");
186     gtk_widget_show (shade_waveform);
187     gtk_box_pack_start (GTK_BOX (vbox02), shade_waveform, TRUE, TRUE, 0);
188 
189     downmix_to_mono = gtk_check_button_new_with_label ("Downmix to mono");
190     gtk_widget_show (downmix_to_mono);
191     gtk_box_pack_start (GTK_BOX (vbox01), downmix_to_mono, FALSE, FALSE, 0);
192 
193     log_scale = gtk_check_button_new_with_label ("Logarithmic scale");
194     gtk_widget_show (log_scale);
195     gtk_box_pack_start (GTK_BOX (vbox01), log_scale, FALSE, FALSE, 0);
196 
197     display_rms = gtk_check_button_new_with_label ("Display RMS");
198     gtk_widget_show (display_rms);
199     gtk_box_pack_start (GTK_BOX (vbox01), display_rms, FALSE, FALSE, 0);
200 
201     display_ruler = gtk_check_button_new_with_label ("Display Ruler");
202     gtk_widget_show (display_ruler);
203     gtk_box_pack_start (GTK_BOX (vbox01), display_ruler, FALSE, FALSE, 0);
204 
205     dialog_action_area13 = gtk_dialog_get_action_area (GTK_DIALOG (waveform_properties));
206     gtk_widget_show (dialog_action_area13);
207     gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area13), GTK_BUTTONBOX_END);
208 
209     applybutton1 = gtk_button_new_from_stock ("gtk-apply");
210     gtk_widget_show (applybutton1);
211     gtk_dialog_add_action_widget (GTK_DIALOG (waveform_properties), applybutton1, GTK_RESPONSE_APPLY);
212     gtk_widget_set_can_default (applybutton1, TRUE);
213 
214     cancelbutton1 = gtk_button_new_from_stock ("gtk-cancel");
215     gtk_widget_show (cancelbutton1);
216     gtk_dialog_add_action_widget (GTK_DIALOG (waveform_properties), cancelbutton1, GTK_RESPONSE_CANCEL);
217     gtk_widget_set_can_default (cancelbutton1, TRUE);
218 
219     okbutton1 = gtk_button_new_from_stock ("gtk-ok");
220     gtk_widget_show (okbutton1);
221     gtk_dialog_add_action_widget (GTK_DIALOG (waveform_properties), okbutton1, GTK_RESPONSE_OK);
222     gtk_widget_set_can_default (okbutton1, TRUE);
223 
224     gtk_color_button_set_color (GTK_COLOR_BUTTON (background_color), &CONFIG_BG_COLOR);
225     gtk_color_button_set_color (GTK_COLOR_BUTTON (foreground_color), &CONFIG_FG_COLOR);
226     gtk_color_button_set_color (GTK_COLOR_BUTTON (progressbar_color), &CONFIG_PB_COLOR);
227     gtk_color_button_set_color (GTK_COLOR_BUTTON (foreground_rms_color), &CONFIG_FG_RMS_COLOR);
228     gtk_color_button_set_alpha (GTK_COLOR_BUTTON (background_color), CONFIG_BG_ALPHA);
229     gtk_color_button_set_alpha (GTK_COLOR_BUTTON (foreground_color), CONFIG_FG_ALPHA);
230     gtk_color_button_set_alpha (GTK_COLOR_BUTTON (progressbar_color), CONFIG_PB_ALPHA);
231     gtk_color_button_set_alpha (GTK_COLOR_BUTTON (foreground_rms_color), CONFIG_FG_RMS_ALPHA);
232 
233     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (downmix_to_mono), CONFIG_MIX_TO_MONO);
234     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (log_scale), CONFIG_LOG_ENABLED);
235     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (display_rms), CONFIG_DISPLAY_RMS);
236     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (display_ruler), CONFIG_DISPLAY_RULER);
237     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (shade_waveform), CONFIG_SHADE_WAVEFORM);
238     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (soundcloud_style), CONFIG_SOUNDCLOUD_STYLE);
239     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fill_waveform), CONFIG_FILL_WAVEFORM);
240 
241     gtk_widget_set_sensitive (display_rms, !CONFIG_SOUNDCLOUD_STYLE);
242 
243     switch (CONFIG_RENDER_METHOD) {
244     case SPIKES:
245         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (render_method_spikes), TRUE);
246         break;
247     case BARS:
248         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (render_method_bars), TRUE);
249         break;
250     }
251 
252     for (;;) {
253         int response = gtk_dialog_run (GTK_DIALOG (waveform_properties));
254         if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) {
255             gtk_color_button_get_color (GTK_COLOR_BUTTON (background_color), &CONFIG_BG_COLOR);
256             gtk_color_button_get_color (GTK_COLOR_BUTTON (foreground_color), &CONFIG_FG_COLOR);
257             gtk_color_button_get_color (GTK_COLOR_BUTTON (progressbar_color), &CONFIG_PB_COLOR);
258             gtk_color_button_get_color (GTK_COLOR_BUTTON (foreground_rms_color), &CONFIG_FG_RMS_COLOR);
259             CONFIG_BG_ALPHA = gtk_color_button_get_alpha (GTK_COLOR_BUTTON (background_color));
260             CONFIG_FG_ALPHA = gtk_color_button_get_alpha (GTK_COLOR_BUTTON (foreground_color));
261             CONFIG_PB_ALPHA = gtk_color_button_get_alpha (GTK_COLOR_BUTTON (progressbar_color));
262             CONFIG_FG_RMS_ALPHA = gtk_color_button_get_alpha (GTK_COLOR_BUTTON (foreground_rms_color));
263             CONFIG_MIX_TO_MONO = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (downmix_to_mono));
264             CONFIG_LOG_ENABLED = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (log_scale));
265             CONFIG_DISPLAY_RMS = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (display_rms));
266             CONFIG_DISPLAY_RULER = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (display_ruler));
267             CONFIG_SHADE_WAVEFORM = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (shade_waveform));
268             CONFIG_SOUNDCLOUD_STYLE = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (soundcloud_style));
269             CONFIG_FILL_WAVEFORM = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fill_waveform));
270             gtk_widget_set_sensitive (display_rms, !CONFIG_SOUNDCLOUD_STYLE);
271             if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (render_method_spikes)) == TRUE) {
272                 CONFIG_RENDER_METHOD = SPIKES;
273             }
274             else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (render_method_bars)) == TRUE) {
275                 CONFIG_RENDER_METHOD = BARS;
276             }
277             save_config ();
278             deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
279         }
280         if (response == GTK_RESPONSE_APPLY) {
281             continue;
282         }
283         break;
284     }
285     gtk_widget_destroy (waveform_properties);
286     return;
287 }
288 #pragma GCC diagnostic pop
289 
290