1 #include <glib.h>
2 #include <gtk/gtk.h>
3 #include <audacious/plugin.h>
4 #include <audacious/util.h>
5
6 #include "subsongseek.h"
7 #include "plugin.h"
8
9
10 static GtkWidget *seekpopup = NULL;
11 static GtkObject *subsong_adj;
12 static int seekpopup_open = 0;
13
14
15 static void uade_seek_directly(void);
16 static void uade_seek_next(void);
17 static void uade_seek_previous(void);
18 static void uade_ffwd(void);
19 static void focus_out_event();
20 static void uade_seek_update_display(int subsong);
21
22
get_next_subsong(void)23 static int get_next_subsong(void)
24 {
25 int ispaused;
26 uade_lock();
27 ispaused = uade_is_paused;
28 uade_unlock();
29 if (ispaused == 0) {
30 int newsubsong;
31 int maxsubsong;
32 newsubsong = uade_get_cur_subsong(-1);
33 maxsubsong = uade_get_max_subsong(-1);
34 if (newsubsong == -1)
35 return -1;
36 if (newsubsong == maxsubsong)
37 return -1;
38 newsubsong++;
39 return newsubsong;
40 }
41 return -1;
42 }
43
44
get_previous_subsong(void)45 static int get_previous_subsong(void)
46 {
47 int ispaused;
48 uade_lock();
49 ispaused = uade_is_paused;
50 uade_unlock();
51 if (ispaused == 0) {
52 int newsubsong;
53 newsubsong = uade_get_cur_subsong(-1);
54 if (newsubsong == -1)
55 return -1;
56 if (newsubsong > uade_get_min_subsong(-1)) {
57 newsubsong--;
58 return newsubsong;
59 }
60 }
61 return -1;
62 }
63
64
65 /* popup for seeking to a subsong*/
66
uade_gui_seek_subsong(int to)67 void uade_gui_seek_subsong(int to)
68 {
69 GtkWidget *seek_button_box;
70 GtkWidget *prev_next_button_box;
71 GtkWidget *seek_button_vbox;
72 GtkWidget *seek_slider_box;
73 GtkWidget *hscale;
74
75 GtkWidget *prev_button;
76 GtkWidget *prev_button_frame;
77 GtkWidget *frame;
78 GtkWidget *maxsong_label;
79 GtkWidget *next_button,*ffwd_button;
80 GtkWidget *ffwd_button_frame;
81
82 if (!uade_thread_running) {
83 fprintf(stderr, "uade: BUG! Seek not possible.\n");
84 return;
85 }
86
87 if (seekpopup == NULL) {
88 /* uade's subsong popup */
89 seekpopup = gtk_window_new(GTK_WINDOW_TOPLEVEL);
90 gtk_window_set_title(GTK_WINDOW(seekpopup), "UADE seek subsong");
91 gtk_window_set_position(GTK_WINDOW(seekpopup), GTK_WIN_POS_MOUSE);
92 gtk_container_set_border_width(GTK_CONTAINER(seekpopup), 0);
93
94 gtk_window_set_policy(GTK_WINDOW(seekpopup), FALSE, FALSE, FALSE);
95
96 gtk_signal_connect(GTK_OBJECT(seekpopup), "destroy",
97 GTK_SIGNAL_FUNC(gtk_widget_destroyed),
98 &seekpopup);
99
100 gtk_signal_connect(GTK_OBJECT(seekpopup), "focus_out_event",
101 GTK_SIGNAL_FUNC(focus_out_event), NULL);
102
103 gtk_widget_realize(seekpopup);
104 gdk_window_set_decorations(seekpopup->window, 0);
105
106 /* define Slider code, will be used by all styles of the popup */
107
108 if (uade_get_max_subsong(-1) >= 0) {
109
110 subsong_adj =
111 gtk_adjustment_new(uade_get_cur_subsong(0), uade_get_min_subsong(0),
112 uade_get_max_subsong(0), 1, 0, 0); /*our scale for the subsong slider */
113 maxsong_label =
114 gtk_label_new(g_strdup_printf("%d", uade_get_max_subsong(0))); /* until we can't get the reliable maximum number of subsongs this has to do :-) */
115 gtk_widget_set_usize(maxsong_label, 24, -1);
116
117 } else {
118 subsong_adj =
119 gtk_adjustment_new(uade_get_cur_subsong(0), uade_get_min_subsong(0),
120 (uade_get_max_subsong(0)) + 10, 1, 0, 0); /*our scale for the subsong slider */
121 /*currently: min - min+10 */
122 maxsong_label = gtk_label_new("..."); /* until we can't get the reliable maximum number of subsongs this has to do :-) */
123 gtk_widget_set_usize(maxsong_label, 24, -1);
124 }
125
126 hscale = gtk_hscale_new(GTK_ADJUSTMENT(subsong_adj));
127 gtk_widget_set_usize(hscale, 160, -1);
128 gtk_scale_set_digits(GTK_SCALE(hscale), 0);
129 gtk_scale_set_value_pos(GTK_SCALE(hscale), GTK_POS_LEFT);
130 gtk_scale_set_draw_value(GTK_SCALE(hscale), TRUE);
131 gtk_range_set_update_policy(GTK_RANGE(hscale),
132 GTK_UPDATE_DISCONTINUOUS);
133 gtk_signal_connect_object(GTK_OBJECT(subsong_adj), "value_changed",
134 GTK_SIGNAL_FUNC(uade_seek_directly),
135 NULL);
136
137
138 /* previous subsong button, will be used by all styles of the seek popup*/
139 prev_button = gtk_button_new_with_label("<");
140 gtk_widget_set_usize(prev_button, 27, -1);
141 gtk_signal_connect_object(GTK_OBJECT(prev_button), "clicked",
142 GTK_SIGNAL_FUNC(uade_seek_previous),
143 NULL);
144
145 prev_button_frame = gtk_frame_new(NULL);
146 gtk_frame_set_shadow_type(GTK_FRAME(prev_button_frame),
147 GTK_SHADOW_IN);
148
149
150 /* next subsong button, will be used by all styles of the seek popup*/
151 next_button = gtk_button_new_with_label(">");
152 gtk_widget_set_usize(next_button, 27, -1);
153 gtk_signal_connect_object(GTK_OBJECT(next_button), "clicked",
154 GTK_SIGNAL_FUNC(uade_seek_next), NULL);
155
156 ffwd_button_frame = gtk_frame_new(NULL);
157 gtk_frame_set_shadow_type(GTK_FRAME(ffwd_button_frame),
158 GTK_SHADOW_IN);
159
160 ffwd_button = gtk_button_new_with_label("10s fwd");
161 gtk_widget_set_usize(ffwd_button, 27, -1);
162 gtk_signal_connect_object(GTK_OBJECT(ffwd_button), "clicked",
163 GTK_SIGNAL_FUNC(uade_ffwd), NULL);
164
165 /* with the alternative styles of the subsongseeker,
166 * following suggestions made by David Le Corfec*/
167 seek_button_box = gtk_hbox_new(FALSE, 0);
168 gtk_container_add(GTK_CONTAINER(seekpopup), seek_button_box);
169
170 frame = gtk_frame_new(NULL);
171 gtk_box_pack_start_defaults(GTK_BOX(seek_button_box), frame);
172 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
173
174
175 seek_button_vbox = gtk_vbox_new(FALSE, 0);
176 gtk_container_add(GTK_CONTAINER(frame), seek_button_vbox);
177 gtk_signal_connect(GTK_OBJECT(seek_button_vbox), "focus_out_event",
178 GTK_SIGNAL_FUNC(focus_out_event), NULL);
179
180 prev_next_button_box = gtk_hbox_new(FALSE, 0);
181
182 /* use the previous defined buttons here */
183
184 gtk_box_pack_start_defaults(GTK_BOX(seek_button_vbox),
185 prev_button_frame);
186
187 gtk_container_add(GTK_CONTAINER(prev_button_frame),
188 prev_next_button_box);
189
190 gtk_box_pack_start_defaults(GTK_BOX(prev_next_button_box),
191 prev_button);
192 gtk_box_pack_start_defaults(GTK_BOX(prev_next_button_box),
193 next_button);
194
195
196
197 seek_slider_box = gtk_hbox_new(FALSE, 0);
198 gtk_box_pack_start(GTK_BOX(seek_button_vbox), seek_slider_box,
199 FALSE, FALSE, 0);
200
201 /* use the previous defined slider and label here */
202 gtk_box_pack_start(GTK_BOX(seek_slider_box), hscale, FALSE, FALSE,
203 0);
204 gtk_box_pack_start(GTK_BOX(seek_slider_box), maxsong_label, FALSE,
205 FALSE, 0);
206
207 /* use the previous defined buttons here */
208 gtk_box_pack_start_defaults(GTK_BOX(seek_button_vbox),
209 ffwd_button_frame);
210 gtk_container_add(GTK_CONTAINER(ffwd_button_frame),
211 ffwd_button);
212
213 gtk_widget_show_all(seekpopup);
214 seekpopup_open = 1;
215
216 } else {
217 gdk_window_raise(seekpopup->window);
218 }
219 }
220
221
uade_gui_subsong_changed(int subsong)222 void uade_gui_subsong_changed(int subsong)
223 {
224 if (seekpopup_open) {
225 GTK_ADJUSTMENT(subsong_adj)->value=subsong;
226 gtk_adjustment_changed(GTK_ADJUSTMENT(subsong_adj)); /*here GTK gets the signal */
227 }
228 }
229
230
uade_seek_directly(void)231 static void uade_seek_directly(void)
232 {
233 /* get the subsong the user selected from scale */
234 int subsong = (gint) GTK_ADJUSTMENT(subsong_adj)->value;
235 int cursub = uade_get_cur_subsong(-1);
236 if (cursub >= 0 && cursub != subsong)
237 uade_select_sub = subsong;
238 }
239
240
241 /* uade_seek_next() and uade_seek_previous ()
242 *
243 * Some desc: the functions get_next_subsong() and get_previous_previous() in
244 * uade.c only do some checking and return the new valid subsongnumber.
245 * the subsongchanging is done in uade_seek_directly()!
246 *
247 * uade_seek_directly itself is not (!) called literally from uade_seek_next()
248 * and previous, but we are updating the value of hscale and thanks to
249 * GTK signalling the uade_seek_directly is invoked automatically.
250 * A bit tricky but it works ;-)
251 */
252
uade_ffwd(void)253 static void uade_ffwd(void)
254 {
255 uade_lock();
256 uade_seek_forward += 10;
257 uade_unlock();
258 }
259
260
uade_seek_next(void)261 static void uade_seek_next(void)
262 {
263 int subsong = get_next_subsong();
264 if (subsong != -1) {
265 /* Call update scale with new subsong */
266 uade_seek_update_display(subsong);
267 }
268 }
269
uade_seek_previous(void)270 static void uade_seek_previous(void)
271 {
272 int subsong = get_previous_subsong(); /* just returns subsong-- */
273 if (subsong != -1) {
274 /* Call update scale with new subsong */
275 uade_seek_update_display(subsong);
276 }
277 }
278
uade_seek_update_display(int subsong)279 static void uade_seek_update_display(int subsong)
280 {
281 /*update scale with new subsong value */
282 GTK_ADJUSTMENT(subsong_adj)->value=subsong;
283 gtk_adjustment_value_changed(GTK_ADJUSTMENT(subsong_adj)); /*here GTK gets the signal */
284 }
285
286
focus_out_event(void)287 static void focus_out_event(void)
288 {
289 seekpopup_open = 0;
290 gtk_widget_destroy(seekpopup);
291 }
292
293 /* Don't know. Is it a good thing to clean up our mess (aka windows)
294 * after stop() was called ???
295 */
uade_gui_close_subsong_win(void)296 void uade_gui_close_subsong_win(void)
297 {
298 if (seekpopup){
299 seekpopup_open = 0;
300 gtk_widget_destroy(seekpopup);
301 }
302 }
303