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