mp3splt-gtk
player_window.c
Go to the documentation of this file.
1 /**********************************************************
2  * mp3splt-gtk -- utility based on mp3splt,
3  *
4  * for mp3/ogg splitting without decoding
5  *
6  * Copyright: (C) 2005-2012 Alexandru Munteanu
7  * Contact: io_fx@yahoo.fr
8  *
9  * http://mp3splt.sourceforge.net/
10  *
11  *********************************************************/
12 
13 /**********************************************************
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28  * USA.
29  *
30  *********************************************************/
31 
32 /*!********************************************************
33  * \file
34  * The player control tab
35  *
36  * this file is used for the player control tab
37  **********************************************************/
38 
39 #include "player_window.h"
40 
41 #define DRAWING_AREA_WIDTH 400
42 #define DRAWING_AREA_HEIGHT 123
43 #define DRAWING_AREA_HEIGHT_WITH_SILENCE_WAVE 232
44 
45 //playlist tree enumeration
46 enum {
47  COL_NAME,
48  COL_FILENAME,
49  PLAYLIST_COLUMNS
50 };
51 
52 static void draw_small_rectangle(gint time_left, gint time_right,
53  GdkColor color, cairo_t *cairo_surface, ui_state *ui);
54 static gint mytimer(ui_state *ui);
55 
57 static void get_silence_level(long time, float level, void *user_data)
58 {
59  ui_state *ui = (ui_state *)user_data;
60 
61  gint converted_level = (gint)floorf(abs(level));
62  if (converted_level < 0)
63  {
64  return;
65  }
66 
67  //TODO: using an idle here does not work.
68  // At least on windows idles are not executed in order
69 
70  if (!ui->infos->silence_points)
71  {
72  ui->infos->silence_points = g_malloc(sizeof(silence_wave) * 3000);
73  ui->infos->malloced_num_of_silence_points = 3000;
74  }
75  else if (ui->infos->number_of_silence_points >= ui->infos->malloced_num_of_silence_points)
76  {
77  ui->infos->silence_points = g_realloc(ui->infos->silence_points,
78  sizeof(silence_wave) * (ui->infos->number_of_silence_points + 3000));
79  ui->infos->malloced_num_of_silence_points = ui->infos->number_of_silence_points + 3000;
80  }
81 
82  ui->infos->silence_points[ui->infos->number_of_silence_points].time = time;
83  ui->infos->silence_points[ui->infos->number_of_silence_points].level = abs(level);
84 
85  ui->infos->number_of_silence_points++;
86 }
87 
88 static GArray *build_gdk_points_for_douglas_peucker(ui_infos *infos)
89 {
90  GArray *points = g_array_new(TRUE, TRUE, sizeof(GdkPoint));
91 
92  gint i = 0;
93  for (i = 0;i < infos->number_of_silence_points;i++)
94  {
95  long time = infos->silence_points[i].time;
96  float level = infos->silence_points[i].level;
97 
98  GdkPoint point;
99  point.x = (gint)time;
100  point.y = (gint)floorf(level);
101  g_array_append_val(points, point);
102  }
103 
104  return points;
105 }
106 
107 static void douglas_peucker_callback(ui_state *ui)
108 {
109  ui->status->douglas_callback_counter++;
110 
111  if (ui->status->douglas_callback_counter % 400 != 0)
112  {
113  return;
114  }
115 
116  gtk_progress_bar_pulse(ui->gui->percent_progress_bar);
117  gtk_progress_bar_set_text(ui->gui->percent_progress_bar,
118  _("Processing Douglas-Peucker filters ..."));
119  gtk_widget_queue_draw(GTK_WIDGET(ui->gui->percent_progress_bar));
120  while (gtk_events_pending())
121  {
122  gtk_main_iteration();
123  }
124 
125  ui->status->douglas_callback_counter = 0;
126 }
127 
128 void compute_douglas_peucker_filters(ui_state *ui)
129 {
130  if (!ui->status->show_silence_wave || ui->status->currently_compute_douglas_peucker_filters)
131  {
132  return;
133  }
134 
135  ui_infos *infos = ui->infos;
136  gui_status *status = ui->status;
137 
138  status->currently_compute_douglas_peucker_filters = TRUE;
139 
140  status->douglas_callback_counter = 0;
141 
142  GArray *gdk_points_for_douglas_peucker = build_gdk_points_for_douglas_peucker(infos);
143 
144  splt_douglas_peucker_free(infos->filtered_points_presence);
145 
146  infos->filtered_points_presence =
147  splt_douglas_peucker(gdk_points_for_douglas_peucker, douglas_peucker_callback, ui,
148  infos->douglas_peucker_thresholds[0], infos->douglas_peucker_thresholds[1],
149  infos->douglas_peucker_thresholds[2], infos->douglas_peucker_thresholds[3],
150  infos->douglas_peucker_thresholds[4], -1.0);
151 
152  g_array_free(gdk_points_for_douglas_peucker, TRUE);
153 
155 
156  status->currently_compute_douglas_peucker_filters = FALSE;
157 }
158 
159 void set_currently_scanning_for_silence_safe(gint value, ui_state *ui)
160 {
161  lock_mutex(&ui->variables_mutex);
162  ui->status->currently_scanning_for_silence = value;
163  unlock_mutex(&ui->variables_mutex);
164 }
165 
166 gint get_currently_scanning_for_silence_safe(ui_state *ui)
167 {
168  lock_mutex(&ui->variables_mutex);
169  gint currently_scanning_for_silence = ui->status->currently_scanning_for_silence;
170  unlock_mutex(&ui->variables_mutex);
171 
172  return currently_scanning_for_silence;
173 }
174 
175 static gboolean detect_silence_end(ui_with_err *ui_err)
176 {
177  ui_state *ui = ui_err->ui;
178 
179  mp3splt_set_silence_level_function(ui->mp3splt_state, NULL, NULL);
180 
181  set_is_splitting_safe(FALSE, ui);
182  set_currently_scanning_for_silence_safe(FALSE, ui);
183 
184  compute_douglas_peucker_filters(ui);
185 
186  print_status_bar_confirmation(ui_err->err, ui);
187  gtk_widget_set_sensitive(ui->gui->cancel_button, FALSE);
188 
189  refresh_drawing_area(ui->gui);
190  refresh_preview_drawing_areas(ui->gui);
191 
192  set_process_in_progress_and_wait_safe(FALSE, ui_err->ui);
193 
194  g_free(ui_err);
195 
196  return FALSE;
197 }
198 
199 static gpointer detect_silence(ui_state *ui)
200 {
201  set_process_in_progress_and_wait_safe(TRUE, ui);
202 
203  set_is_splitting_safe(TRUE, ui);
204  set_currently_scanning_for_silence_safe(TRUE, ui);
205 
206  if (ui->infos->silence_points)
207  {
208  g_free(ui->infos->silence_points);
209  ui->infos->silence_points = NULL;
210  ui->infos->number_of_silence_points = 0;
211  }
212 
213  enter_threads();
214  gtk_widget_set_sensitive(ui->gui->cancel_button, TRUE);
215  exit_threads();
216 
217  lock_mutex(&ui->variables_mutex);
218  mp3splt_set_filename_to_split(ui->mp3splt_state, get_input_filename(ui->gui));
219  unlock_mutex(&ui->variables_mutex);
220 
221  mp3splt_set_silence_level_function(ui->mp3splt_state, get_silence_level, ui);
222 
223  gint err = SPLT_OK;
224  mp3splt_set_silence_points(ui->mp3splt_state, &err);
225 
226  ui_with_err *ui_err = g_malloc0(sizeof(ui_with_err));
227  ui_err->err = err;
228  ui_err->ui = ui;
229 
230  gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)detect_silence_end, ui_err, NULL);
231 
232  return NULL;
233 }
234 
235 static void detect_silence_action(ui_state *ui)
236 {
237  create_thread((GThreadFunc)detect_silence, ui);
238 }
239 
244 static void scan_for_silence_wave(ui_state *ui)
245 {
246  if (get_currently_scanning_for_silence_safe(ui))
247  {
248  cancel_button_event(ui->gui->cancel_button, ui);
249  }
250 
251  if (ui->status->timer_active)
252  {
253  detect_silence_action(ui);
254  }
255 }
256 
262 void change_current_filename(const gchar *fname, ui_state *ui)
263 {
264  const gchar *old_fname = get_input_filename(ui->gui);
265  if (!old_fname)
266  {
267  set_input_filename(fname, ui);
268 
269  if (ui->status->show_silence_wave)
270  {
271  scan_for_silence_wave(ui);
272  }
273 
274  if (gtk_toggle_button_get_active(ui->gui->names_from_filename))
275  {
276  copy_filename_to_current_description(fname, ui);
277  }
278 
279  return;
280  }
281 
282  if (strcmp(old_fname, fname) == 0)
283  {
284  return;
285  }
286 
287  set_input_filename(fname, ui);
288  if (ui->status->show_silence_wave)
289  {
290  scan_for_silence_wave(ui);
291  }
292 
293  if (gtk_toggle_button_get_active(ui->gui->names_from_filename))
294  {
295  copy_filename_to_current_description(fname, ui);
296  }
297 }
298 
300 static void reset_inactive_progress_bar(gui_state *gui)
301 {
302  gtk_widget_set_sensitive(GTK_WIDGET(gui->progress_bar), FALSE);
303  gtk_adjustment_set_value(gui->progress_adj, 0);
304 }
305 
307 static void reset_inactive_volume_button(gui_state *gui)
308 {
309  gtk_widget_set_sensitive(GTK_WIDGET(gui->volume_button), FALSE);
310  gtk_scale_button_set_value(GTK_SCALE_BUTTON(gui->volume_button), 0);
311 }
312 
314 static void reset_label_time(gui_state *gui)
315 {
316  gtk_label_set_text(GTK_LABEL(gui->label_time), "");
317 }
318 
320 static void reset_song_infos(gui_state *gui)
321 {
322  gtk_label_set_text(GTK_LABEL(gui->song_infos),"");
323 }
324 
326 static void reset_song_name_label(gui_state *gui)
327 {
328  gtk_label_set_text(GTK_LABEL(gui->song_name_label), "");
329 }
330 
332 static void clear_data_player(gui_state *gui)
333 {
334  reset_song_name_label(gui);
335  reset_song_infos(gui);
336  reset_inactive_volume_button(gui);
337  reset_inactive_progress_bar(gui);
338  reset_label_time(gui);
339 }
340 
343 {
344  gui_state *gui = ui->gui;
345 
346  gtk_widget_set_sensitive(gui->stop_button, TRUE);
347  wh_set_image_on_button(GTK_BUTTON(gui->stop_button), g_object_ref(gui->StopButton_active));
348 
349  gtk_widget_set_sensitive(gui->pause_button, TRUE);
350  wh_set_image_on_button(GTK_BUTTON(gui->pause_button), g_object_ref(gui->PauseButton_active));
351 
352  if (ui->infos->selected_player != PLAYER_GSTREAMER)
353  {
354  gtk_widget_set_sensitive(gui->go_beg_button, TRUE);
355  wh_set_image_on_button(GTK_BUTTON(gui->go_beg_button), g_object_ref(gui->Go_BegButton_active));
356 
357  gtk_widget_set_sensitive(gui->go_end_button, TRUE);
358  wh_set_image_on_button(GTK_BUTTON(gui->go_end_button), g_object_ref(gui->Go_EndButton_active));
359  }
360 
361  gtk_widget_set_sensitive(gui->play_button, TRUE);
362  wh_set_image_on_button(GTK_BUTTON(gui->play_button), g_object_ref(gui->PlayButton_active));
363 
364  player_key_actions_set_sensitivity(TRUE, gui);
365 }
366 
368 static void disable_player_buttons(gui_state *gui)
369 {
370  gtk_widget_set_sensitive(gui->stop_button, FALSE);
371  wh_set_image_on_button(GTK_BUTTON(gui->stop_button), g_object_ref(gui->StopButton_inactive));
372 
373  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui->pause_button), FALSE);
374  gtk_widget_set_sensitive(gui->pause_button, FALSE);
375  wh_set_image_on_button(GTK_BUTTON(gui->pause_button), g_object_ref(gui->PauseButton_inactive));
376 
377  gtk_widget_set_sensitive(gui->go_beg_button, FALSE);
378  wh_set_image_on_button(GTK_BUTTON(gui->go_beg_button), g_object_ref(gui->Go_BegButton_inactive));
379 
380  gtk_widget_set_sensitive(gui->go_end_button, FALSE);
381  wh_set_image_on_button(GTK_BUTTON(gui->go_end_button), g_object_ref(gui->Go_EndButton_inactive));
382 
383  gtk_widget_set_sensitive(gui->play_button, FALSE);
384  wh_set_image_on_button(GTK_BUTTON(gui->play_button), g_object_ref(gui->PlayButton_inactive));
385 
386  gtk_widget_set_sensitive(gui->player_add_button, FALSE);
387  gtk_widget_set_sensitive(gui->silence_wave_check_button, FALSE);
388 
389  player_key_actions_set_sensitivity(FALSE, gui);
390 }
391 
393 static void show_disconnect_button(gui_state *gui)
394 {
395  if (!wh_container_has_child(GTK_CONTAINER(gui->player_buttons_hbox), gui->disconnect_button))
396  {
397  gtk_box_pack_start(gui->player_buttons_hbox, gui->disconnect_button, FALSE, FALSE, 7);
398  }
399 
400  gtk_widget_show_all(gui->disconnect_button);
401 }
402 
405 {
406  gtk_widget_hide(gui->connect_button);
407 }
408 
410 static void connect_change_buttons(ui_state *ui)
411 {
412  if (ui->infos->selected_player == PLAYER_GSTREAMER)
413  {
414  return;
415  }
416 
417  show_disconnect_button(ui->gui);
418  hide_connect_button(ui->gui);
419 }
420 
422 static void hide_disconnect_button(gui_state *gui)
423 {
424  gtk_widget_hide(gui->disconnect_button);
425 }
426 
429 {
430  if (!wh_container_has_child(GTK_CONTAINER(gui->player_buttons_hbox), gui->connect_button))
431  {
432  gtk_box_pack_start(gui->player_buttons_hbox, gui->connect_button, FALSE, FALSE, 7);
433  }
434 
435  gtk_widget_show_all(gui->connect_button);
436 }
437 
439 static void disconnect_change_buttons(ui_state *ui)
440 {
441  if (ui->infos->selected_player == PLAYER_GSTREAMER)
442  {
443  return;
444  }
445 
446  hide_disconnect_button(ui->gui);
447  show_connect_button(ui->gui);
448 }
449 
457 static void connect_with_song(const gchar *fname, gint start_playing, ui_state *ui)
458 {
459  if (fname == NULL)
460  {
461  return;
462  }
463 
464  gui_status *status = ui->status;
465 
466  GList *song_list = NULL;
467  song_list = g_list_append(song_list, strdup(fname));
468 
469  if (start_playing == 0)
470  {
471  if (!player_is_running(ui))
472  {
473  player_start_play_with_songs(song_list, ui);
474  }
475  else
476  {
477  player_add_play_files(song_list, ui);
478  }
479  }
480  else
481  {
482  if (status->file_browsed)
483  {
484  //if the player is not running, start it ,queue to playlist and
485  //play the file
486  if (!player_is_running(ui))
487  {
488  player_start_add_files(song_list, ui);
489  }
490  else
491  {
492  if (!status->playing)
493  {
494  player_add_files_and_select(song_list, ui);
495  }
496  else
497  {
498  player_add_files(song_list, ui);
499  }
500  }
501  }
502  }
503 
504  status->playing = player_is_playing(ui);
505 
506  if (!status->timer_active)
507  {
508  status->timeout_id = g_timeout_add(ui->infos->timeout_value, (GSourceFunc)mytimer, ui);
509  status->timer_active = TRUE;
510  }
511 
513 
514  if (player_is_running(ui))
515  {
516  connect_change_buttons(ui);
517  }
518 
519  g_list_foreach(song_list, (GFunc)g_free, NULL);
520  g_list_free(song_list);
521 }
522 
529 {
530  connect_with_song(get_input_filename(ui->gui), i, ui);
531 }
532 
534 void connect_button_event(GtkWidget *widget, ui_state *ui)
535 {
536  gui_status *status = ui->status;
537 
538  if (!player_is_running(ui))
539  {
540  player_start(ui);
541  }
542 
543  mytimer(ui);
544 
545  if (!status->timer_active)
546  {
547  if (ui->infos->selected_player == PLAYER_SNACKAMP)
548  {
549  connect_snackamp(8775, ui);
550  }
551 
552  status->timeout_id = g_timeout_add(ui->infos->timeout_value, (GSourceFunc)mytimer, ui);
553  status->timer_active = TRUE;
554  }
555 
556  //connect to player with song
557  //1 means dont start playing
559 
561 
562  status->file_browsed = FALSE;
563  status->change_volume = TRUE;
564 
565  //here we check if we have been connected
566  if (player_is_running(ui))
567  {
568  connect_change_buttons(ui);
569  }
570  else
571  {
572  GtkWidget *label;
573  switch (ui->infos->selected_player)
574  {
575  case PLAYER_SNACKAMP:
576  label = gtk_label_new
577  (_("\n Cannot connect to snackAmp player.\n"
578  " Please download and install snackamp from\n"
579  "\thttp://snackamp.sourceforge.net\n\n"
580  " Verify that snackamp is running.\n"
581  " Verify that your snackamp version is >= 3.1.3\n\n"
582  " Verify that you have enabled socket interface in snackamp:\n"
583  " You have to go to\n"
584  "\tTools->Preferences->Miscellaneous\n"
585  " from the snackamp menu and check\n"
586  "\tEnable Socket Interface\n"
587  " Only default port is supported for now(8775)\n"
588  " After that, restart snackamp and mp3splt-gtk should work.\n"));
589  break;
590  case PLAYER_AUDACIOUS:
591  label = gtk_label_new
592  (_("\n Cannot connect to Audacious player.\n"
593  " Verify that you have installed audacious.\n\n"
594  " Put in your PATH variable the directory where the audacious"
595  " executable is.\n"
596  " If you don't know how to do that, start audacious manually"
597  " and then try to connect.\n"));
598  break;
599  default:
600  label = gtk_label_new(_("Cannot connect to player"));
601  break;
602  }
603 
604  GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Cannot connect to player"),
605  GTK_WINDOW(ui->gui->window), GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_NONE, NULL);
606  g_signal_connect_swapped(dialog, "response", G_CALLBACK(gtk_widget_destroy), dialog);
607  gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), label);
608  gtk_widget_show_all(dialog);
609  }
610 
611  ui->infos->current_time = -1;
613 
614  if (ui->status->show_silence_wave)
615  {
616  scan_for_silence_wave(ui);
617  }
618 
619  mytimer(ui);
620  refresh_drawing_area(ui->gui);
621 }
622 
624 static void check_stream(ui_state *ui)
625 {
626  if (((gint)ui->infos->total_time) == -1)
627  {
628  ui->status->stream = TRUE;
629  reset_inactive_progress_bar(ui->gui);
630  }
631  else
632  {
633  ui->status->stream = FALSE;
634  }
635 }
636 
638 void disconnect_button_event(GtkWidget *widget, ui_state *ui)
639 {
640  gui_state *gui = ui->gui;
641 
642  if (ui->status->timer_active)
643  {
644  if (ui->infos->selected_player == PLAYER_SNACKAMP)
645  {
647  }
648 
649  g_source_remove(ui->status->timeout_id);
650  ui->status->timer_active = FALSE;
651  }
652 
653  clear_data_player(gui);
654  disconnect_change_buttons(ui);
655  disable_player_buttons(gui);
656 
657  //update bottom progress bar to 0 and ""
658  if (!get_is_splitting_safe(ui))
659  {
660  gtk_progress_bar_set_fraction(gui->percent_progress_bar, 0);
661  gtk_progress_bar_set_text(gui->percent_progress_bar, "");
662  }
663 
664  const gchar *fname = get_input_filename(gui);
665  if (file_exists(fname))
666  {
667  gtk_widget_set_sensitive(gui->play_button, TRUE);
668  wh_set_image_on_button(GTK_BUTTON(gui->play_button), g_object_ref(gui->PlayButton_active));
669  }
670 
671  player_quit(ui);
672 
673  if (get_currently_scanning_for_silence_safe(ui))
674  {
675  cancel_button_event(ui->gui->cancel_button, ui);
676  }
677 
678  refresh_drawing_area(ui->gui);
679 }
680 
681 void restart_player_timer(ui_state *ui)
682 {
683  if (ui->status->timer_active)
684  {
685  g_source_remove(ui->status->timeout_id);
686  ui->status->timeout_id = g_timeout_add(ui->infos->timeout_value, (GSourceFunc)mytimer, ui);
687  }
688 }
689 
691 static void play_event(GtkWidget *widget, ui_state *ui)
692 {
693  gui_state *gui = ui->gui;
694  gui_status *status = ui->status;
695 
696  if (status->timer_active)
697  {
698  if (!player_is_running(ui))
699  {
700  player_start(ui);
701  }
702  player_play(ui);
703  status->playing = player_is_playing(ui);
704  }
705  else
706  {
707  //0 = also start playing
709  }
710 
711  gtk_widget_set_sensitive(gui->pause_button, TRUE);
712  wh_set_image_on_button(GTK_BUTTON(gui->pause_button), g_object_ref(gui->PauseButton_active));
713 
714  gtk_widget_set_sensitive(gui->stop_button, TRUE);
715  wh_set_image_on_button(GTK_BUTTON(gui->stop_button), g_object_ref(gui->StopButton_active));
716 }
717 
719 static void stop_event(GtkWidget *widget, ui_state *ui)
720 {
721  gui_state *gui = ui->gui;
722 
723  if (!ui->status->timer_active)
724  {
725  return;
726  }
727 
728  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui->pause_button), FALSE);
729 
730  if (player_is_running(ui))
731  {
732  ui->status->playing = FALSE;
733  }
734 
735  player_stop(ui);
736 
737  gtk_widget_set_sensitive(gui->pause_button, FALSE);
738  wh_set_image_on_button(GTK_BUTTON(gui->pause_button), g_object_ref(gui->PauseButton_inactive));
739 
740  gtk_widget_set_sensitive(gui->stop_button, FALSE);
741  wh_set_image_on_button(GTK_BUTTON(gui->stop_button), g_object_ref(gui->StopButton_inactive));
742 }
743 
745 void pause_event(GtkWidget *widget, ui_state *ui)
746 {
747  if (!ui->status->timer_active) { return; }
748  if (!player_is_running(ui)) { return; }
749  if (ui->status->only_press_pause) { return; }
750 
751  player_pause(ui);
752 }
753 
755 static void prev_button_event(GtkWidget *widget, ui_state *ui)
756 {
757  if (!ui->status->timer_active) { return; }
758  if (!player_is_running(ui)) { return; }
759  player_prev(ui);
760 }
761 
763 static void next_button_event(GtkWidget *widget, ui_state *ui)
764 {
765  if (!ui->status->timer_active)
766  {
767  return;
768  }
769 
770  if (!player_is_running(ui))
771  {
772  return;
773  }
774 
775  player_next(ui);
776 }
777 
779 static void change_song_position(ui_state *ui)
780 {
781  gint position =
782  ui->infos->player_seconds2 * 1000 +
783  ui->infos->player_minutes2 * 60000 +
784  ui->infos->player_hundr_secs2 * 10;
785 
786  player_seek(position, ui);
787 }
788 
790 static void toggle_show_silence_wave(GtkToggleButton *show_silence_toggle_button, ui_state *ui)
791 {
792  ui_infos *infos = ui->infos;
793  gui_status *status = ui->status;
794 
795  if (gtk_toggle_button_get_active(show_silence_toggle_button))
796  {
797  status->show_silence_wave = TRUE;
798  scan_for_silence_wave(ui);
799  return;
800  }
801 
802  status->show_silence_wave = FALSE;
803  if (get_currently_scanning_for_silence_safe(ui))
804  {
805  cancel_button_event(ui->gui->cancel_button, ui);
806  }
807 
808  refresh_drawing_area(ui->gui);
809  refresh_preview_drawing_areas(ui->gui);
810 }
811 
813 static gboolean volume_button_unclick_event(GtkWidget *widget, GdkEventCrossing *event, ui_state *ui)
814 {
815  ui->status->change_volume = TRUE;
816  return FALSE;
817 }
818 
820 static gboolean volume_button_click_event(GtkWidget *widget, GdkEventCrossing *event, ui_state *ui)
821 {
822  ui->status->change_volume = FALSE;
823  return FALSE;
824 }
825 
827 static gboolean volume_button_enter_event(GtkWidget *widget, GdkEventCrossing *event, ui_state *ui)
828 {
829  ui->status->on_the_volume_button = TRUE;
830  return FALSE;
831 }
832 
834 static gboolean volume_button_leave_event(GtkWidget *widget, GdkEventCrossing *event, ui_state *ui)
835 {
836  ui->status->on_the_volume_button = FALSE;
837  return FALSE;
838 }
839 
841 static void change_volume_event(GtkScaleButton *volume_button, gdouble value, ui_state *ui)
842 {
843  if (!gtk_widget_get_sensitive(GTK_WIDGET(volume_button)))
844  {
845  return;
846  }
847 
848  player_set_volume((gint)(value * 100), ui);
849 }
850 
851 static GtkWidget *create_volume_button(ui_state *ui)
852 {
853  GtkWidget *volume_button = gtk_volume_button_new();
854  ui->gui->volume_button = volume_button;
855 
856  g_signal_connect(G_OBJECT(volume_button), "button-press-event",
857  G_CALLBACK(volume_button_click_event), ui);
858  g_signal_connect(G_OBJECT(volume_button), "button-release-event",
859  G_CALLBACK(volume_button_unclick_event), ui);
860  g_signal_connect(G_OBJECT(volume_button), "enter-notify-event",
861  G_CALLBACK(volume_button_enter_event), ui);
862  g_signal_connect(G_OBJECT(volume_button), "leave-notify-event",
863  G_CALLBACK(volume_button_leave_event), ui);
864 
865  g_signal_connect(GTK_SCALE_BUTTON(volume_button), "value_changed",
866  G_CALLBACK(change_volume_event), ui);
867 
868  gtk_widget_set_sensitive(GTK_WIDGET(volume_button), FALSE);
869 
870  return volume_button;
871 }
872 
874 static GtkWidget *create_player_buttons_hbox(ui_state *ui)
875 {
876  GtkBox *player_buttons_hbox = GTK_BOX(wh_hbox_new());
877  ui->gui->player_buttons_hbox = player_buttons_hbox;
878 
879  GString *imagefile = g_string_new("");
880  build_path(imagefile, IMAGEDIR, "backward"ICON_EXT);
881  GtkWidget *Go_BegButton_active = gtk_image_new_from_file(imagefile->str);
882  ui->gui->Go_BegButton_active = Go_BegButton_active;
883 
884  build_path(imagefile, IMAGEDIR, "backward_inactive"ICON_EXT);
885  GtkWidget *Go_BegButton_inactive = gtk_image_new_from_file(imagefile->str);
886  ui->gui->Go_BegButton_inactive = Go_BegButton_inactive;
887  GtkWidget *go_beg_button = gtk_button_new();
888  ui->gui->go_beg_button = go_beg_button;
889  wh_set_image_on_button(GTK_BUTTON(go_beg_button), g_object_ref(Go_BegButton_inactive));
890 
891  gtk_box_pack_start(player_buttons_hbox, go_beg_button, FALSE, FALSE, 0);
892  gtk_button_set_relief(GTK_BUTTON(go_beg_button), GTK_RELIEF_NONE);
893  g_signal_connect(G_OBJECT(go_beg_button), "clicked", G_CALLBACK(prev_button_event), ui);
894  gtk_widget_set_sensitive(go_beg_button, FALSE);
895  gtk_widget_set_tooltip_text(go_beg_button, _("Previous"));
896 
897  //play button
898  build_path(imagefile, IMAGEDIR, "play"ICON_EXT);
899  GtkWidget *PlayButton_active = gtk_image_new_from_file(imagefile->str);
900  ui->gui->PlayButton_active = PlayButton_active;
901 
902  build_path(imagefile, IMAGEDIR, "play_inactive"ICON_EXT);
903  GtkWidget *PlayButton_inactive = gtk_image_new_from_file(imagefile->str);
904  ui->gui->PlayButton_inactive = PlayButton_inactive;
905  GtkWidget *play_button = gtk_button_new();
906  ui->gui->play_button = play_button;
907  wh_set_image_on_button(GTK_BUTTON(play_button), g_object_ref(PlayButton_inactive));
908 
909  gtk_box_pack_start(player_buttons_hbox, play_button, FALSE, FALSE, 0);
910  gtk_button_set_relief(GTK_BUTTON(play_button), GTK_RELIEF_NONE);
911  g_signal_connect(G_OBJECT(play_button), "clicked", G_CALLBACK(play_event), ui);
912  gtk_widget_set_sensitive(play_button, FALSE);
913  gtk_widget_set_tooltip_text(play_button, _("Play"));
914 
915  //pause button
916  build_path(imagefile, IMAGEDIR, "pause"ICON_EXT);
917  GtkWidget *PauseButton_active = gtk_image_new_from_file(imagefile->str);
918  ui->gui->PauseButton_active = PauseButton_active;
919 
920  build_path(imagefile, IMAGEDIR, "pause_inactive"ICON_EXT);
921  GtkWidget *PauseButton_inactive = gtk_image_new_from_file(imagefile->str);
922  ui->gui->PauseButton_inactive = PauseButton_inactive;
923  GtkWidget *pause_button = gtk_toggle_button_new();
924  ui->gui->pause_button = pause_button;
925  wh_set_image_on_button(GTK_BUTTON(pause_button), g_object_ref(PauseButton_inactive));
926  gtk_box_pack_start(player_buttons_hbox, pause_button, FALSE, FALSE, 0);
927  gtk_button_set_relief(GTK_BUTTON(pause_button), GTK_RELIEF_NONE);
928  g_signal_connect(G_OBJECT(pause_button), "clicked", G_CALLBACK(pause_event), ui);
929  gtk_widget_set_sensitive(pause_button, FALSE);
930  gtk_widget_set_tooltip_text(pause_button,_("Pause"));
931 
932  //stop button
933  build_path(imagefile, IMAGEDIR, "stop"ICON_EXT);
934  GtkWidget *StopButton_active = gtk_image_new_from_file(imagefile->str);
935  ui->gui->StopButton_active = StopButton_active;
936 
937  build_path(imagefile, IMAGEDIR, "stop_inactive"ICON_EXT);
938  GtkWidget *StopButton_inactive = gtk_image_new_from_file(imagefile->str);
939  ui->gui->StopButton_inactive = StopButton_inactive;
940  GtkWidget *stop_button = gtk_button_new();
941  ui->gui->stop_button = stop_button;
942  wh_set_image_on_button(GTK_BUTTON(stop_button), g_object_ref(StopButton_inactive));
943  gtk_box_pack_start(player_buttons_hbox, stop_button, FALSE, FALSE, 0);
944  gtk_button_set_relief(GTK_BUTTON(stop_button), GTK_RELIEF_NONE);
945  g_signal_connect(G_OBJECT(stop_button), "clicked", G_CALLBACK(stop_event), ui);
946  gtk_widget_set_sensitive(stop_button, FALSE);
947  gtk_widget_set_tooltip_text(stop_button,_("Stop"));
948 
949  //go at the end button
950  build_path(imagefile, IMAGEDIR, "forward"ICON_EXT);
951  GtkWidget *Go_EndButton_active = gtk_image_new_from_file(imagefile->str);
952  ui->gui->Go_EndButton_active = Go_EndButton_active;
953 
954  build_path(imagefile, IMAGEDIR, "forward_inactive"ICON_EXT);
955  GtkWidget *Go_EndButton_inactive = gtk_image_new_from_file(imagefile->str);
956  ui->gui->Go_EndButton_inactive = Go_EndButton_inactive;
957  GtkWidget *go_end_button = gtk_button_new();
958  ui->gui->go_end_button = go_end_button;
959  wh_set_image_on_button(GTK_BUTTON(go_end_button), g_object_ref(Go_EndButton_inactive));
960  gtk_box_pack_start(player_buttons_hbox, go_end_button, FALSE, FALSE, 0);
961  gtk_button_set_relief(GTK_BUTTON(go_end_button), GTK_RELIEF_NONE);
962  g_signal_connect(G_OBJECT(go_end_button), "clicked", G_CALLBACK(next_button_event), ui);
963  gtk_widget_set_sensitive(go_end_button, FALSE);
964  gtk_widget_set_tooltip_text(go_end_button,_("Next"));
965  g_string_free(imagefile,TRUE);
966 
967  GtkWidget *vol_button = create_volume_button(ui);
968  gtk_box_pack_start(player_buttons_hbox, vol_button, FALSE, FALSE, 5);
969 
970  //add button
971  GtkWidget *player_add_button = wh_create_cool_button(GTK_STOCK_ADD, _("_Add"), FALSE);
972  ui->gui->player_add_button = player_add_button;
973  gtk_box_pack_start(player_buttons_hbox, player_add_button, FALSE, FALSE, 0);
974  gtk_button_set_relief(GTK_BUTTON(player_add_button), GTK_RELIEF_NONE);
975  g_signal_connect(G_OBJECT(player_add_button), "clicked",
976  G_CALLBACK(add_splitpoint_from_player), ui);
977  gtk_widget_set_sensitive(player_add_button, FALSE);
978  gtk_widget_set_tooltip_text(player_add_button,_("Add splitpoint from player"));
979 
980  //set splitpoints from trim silence button
981  GtkWidget *scan_trim_silence_button = wh_create_cool_button(GTK_STOCK_CUT, NULL, FALSE);
982  ui->gui->scan_trim_silence_button_player = scan_trim_silence_button;
983  gtk_widget_set_sensitive(scan_trim_silence_button, TRUE);
984  g_signal_connect(G_OBJECT(scan_trim_silence_button), "clicked",
985  G_CALLBACK(create_trim_silence_window), ui);
986  gtk_widget_set_tooltip_text(scan_trim_silence_button,
987  _("Set trim splitpoints using silence detection"));
988  gtk_box_pack_start(player_buttons_hbox, scan_trim_silence_button, FALSE, FALSE, 0);
989  gtk_button_set_relief(GTK_BUTTON(scan_trim_silence_button), GTK_RELIEF_NONE);
990 
991  //set splitpoints from silence button
992  GtkWidget *scan_silence_button = wh_create_cool_button(GTK_STOCK_FIND_AND_REPLACE, NULL, FALSE);
993  ui->gui->scan_silence_button_player = scan_silence_button;
994  gtk_widget_set_sensitive(scan_silence_button, TRUE);
995  g_signal_connect(G_OBJECT(scan_silence_button), "clicked",
997  gtk_widget_set_tooltip_text(scan_silence_button,
998  _("Set splitpoints from silence detection"));
999  gtk_box_pack_start(player_buttons_hbox, scan_silence_button, FALSE, FALSE, 0);
1000  gtk_button_set_relief(GTK_BUTTON(scan_silence_button), GTK_RELIEF_NONE);
1001 
1002  //silence wave check button
1003  GtkWidget *silence_wave_check_button = gtk_check_button_new_with_mnemonic(_("Amplitude _wave"));
1004  ui->gui->silence_wave_check_button = silence_wave_check_button;
1005  gtk_box_pack_end(player_buttons_hbox, silence_wave_check_button, FALSE, FALSE, 5);
1006  g_signal_connect(G_OBJECT(silence_wave_check_button), "toggled",
1007  G_CALLBACK(toggle_show_silence_wave), ui);
1008  gtk_widget_set_sensitive(silence_wave_check_button, FALSE);
1009  gtk_widget_set_tooltip_text(silence_wave_check_button, _("Shows the amplitude level wave"));
1010 
1011  /* connect player button */
1012  GtkWidget *connect_button = wh_create_cool_button(GTK_STOCK_CONNECT,_("_Connect"), FALSE);
1013  ui->gui->connect_button = connect_button;
1014  g_signal_connect(G_OBJECT(connect_button), "clicked", G_CALLBACK(connect_button_event), ui);
1015  gtk_widget_set_tooltip_text(connect_button,_("Connect to player"));
1016 
1017  /* disconnect player button */
1018  GtkWidget *disconnect_button = wh_create_cool_button(GTK_STOCK_DISCONNECT,_("_Disconnect"), FALSE);
1019  ui->gui->disconnect_button = disconnect_button;
1020  g_signal_connect(G_OBJECT(disconnect_button), "clicked", G_CALLBACK(disconnect_button_event), ui);
1021  gtk_widget_set_tooltip_text(disconnect_button,_("Disconnect from player"));
1022 
1023  return GTK_WIDGET(player_buttons_hbox);
1024 }
1025 
1027 static GtkWidget *create_song_informations_hbox(gui_state *gui)
1028 {
1029  GtkWidget *song_info_hbox = wh_hbox_new();
1030 
1031  GtkWidget *song_infos = gtk_label_new("");
1032  gui->song_infos = song_infos;
1033  gtk_box_pack_start(GTK_BOX(song_info_hbox), song_infos, FALSE, FALSE, 40);
1034 
1035  GtkWidget *label_time = gtk_label_new("");
1036  gui->label_time = label_time;
1037  gtk_box_pack_start(GTK_BOX(song_info_hbox), label_time, FALSE, FALSE, 5);
1038 
1039  return song_info_hbox;
1040 }
1041 
1043 static gboolean progress_bar_unclick_event(GtkWidget *widget, GdkEventCrossing *event, ui_state *ui)
1044 {
1045  change_song_position(ui);
1046 
1047  ui_infos *infos = ui->infos;
1048 
1049  infos->player_minutes = infos->player_minutes2;
1050  infos->player_seconds = infos->player_seconds2;
1051  infos->player_hundr_secs = infos->player_hundr_secs2;
1052 
1053  ui->status->mouse_on_progress_bar = FALSE;
1054 
1055  return FALSE;
1056 }
1057 
1059 static gboolean progress_bar_click_event(GtkWidget *widget, GdkEventCrossing *event, ui_state *ui)
1060 {
1061  ui->status->mouse_on_progress_bar = TRUE;
1062  return FALSE;
1063 }
1064 
1066 static gfloat get_elapsed_time(ui_state *ui)
1067 {
1068  gfloat adj_position = gtk_adjustment_get_value(ui->gui->progress_adj);
1069  return (adj_position * ui->infos->total_time) / 100000;
1070 }
1071 
1072 void refresh_drawing_area(gui_state *gui)
1073 {
1074  gtk_widget_queue_draw(gui->drawing_area);
1075 }
1076 
1079 {
1080  if (get_is_splitting_safe(ui) ||
1081  get_currently_scanning_for_silence_safe(ui) ||
1082  ui->status->currently_compute_douglas_peucker_filters)
1083  {
1084  return;
1085  }
1086 
1087  gfloat progress_time = 0;
1088  gint splitpoint_time_left = -1;
1089  gint splitpoint_time_right = -1;
1090  gint splitpoint_left_index = -1;
1091  get_current_splitpoints_time_left_right(&splitpoint_time_left, &splitpoint_time_right,
1092  &splitpoint_left_index, ui);
1093 
1094  if ((splitpoint_time_left != -1) && (splitpoint_time_right != -1))
1095  {
1096  gfloat total_interval = splitpoint_time_right - splitpoint_time_left;
1097  if (((gint)total_interval) != 0)
1098  {
1099  progress_time = (ui->infos->current_time-splitpoint_time_left) / total_interval;
1100  }
1101  }
1102  else
1103  {
1104  if (splitpoint_time_right == -1)
1105  {
1106  gfloat total_interval = ui->infos->total_time - splitpoint_time_left;
1107  if (((gint)total_interval) != 0)
1108  {
1109  progress_time = (ui->infos->current_time-splitpoint_time_left)/ total_interval;
1110  }
1111  }
1112  else
1113  {
1114  gfloat total_interval = splitpoint_time_right;
1115  if (((gint)total_interval) != 0)
1116  {
1117  progress_time = ui->infos->current_time/total_interval;
1118  }
1119  }
1120  }
1121 
1122  if (progress_time < 0)
1123  {
1124  progress_time = 0;
1125  }
1126  if (progress_time > 1)
1127  {
1128  progress_time = 1;
1129  }
1130  if ((progress_time >= 0) && (progress_time <= 1))
1131  {
1132  gtk_progress_bar_set_fraction(ui->gui->percent_progress_bar, progress_time);
1133  }
1134 
1135  gchar *progress_description = get_splitpoint_name(splitpoint_left_index-1, ui);
1136  gchar description_shorted[512] = { '\0' };
1137 
1138  if (splitpoint_time_right != -1)
1139  {
1140  if (splitpoint_time_left == -1)
1141  {
1142  if (progress_description != NULL)
1143  {
1144  g_snprintf(description_shorted, 60, _("before %s"), progress_description);
1145  }
1146  }
1147  else
1148  {
1149  if (progress_description != NULL)
1150  {
1151  g_snprintf(description_shorted, 60, "%s", progress_description);
1152  }
1153  }
1154  }
1155  else
1156  {
1157  if (splitpoint_time_left != -1)
1158  {
1159  if (progress_description != NULL)
1160  {
1161  g_snprintf(description_shorted, 60, "%s", progress_description);
1162  }
1163  }
1164  else
1165  {
1166  gchar *fname = get_input_filename(ui->gui);
1167  g_snprintf(description_shorted, 60, "%s", get_real_name_from_filename(fname));
1168  }
1169  }
1170 
1171  if (strlen(description_shorted) > 55)
1172  {
1173  description_shorted[56] = '.';
1174  description_shorted[57] = '.';
1175  description_shorted[58] = '.';
1176  description_shorted[59] = '\0';
1177  }
1178 
1179  gtk_progress_bar_set_text(ui->gui->percent_progress_bar, description_shorted);
1180  g_free(progress_description);
1181 }
1182 
1184 static void progress_bar_value_changed_event(GtkRange *range, ui_state *ui)
1185 {
1186  refresh_drawing_area(ui->gui);
1187 
1188  ui_infos *infos = ui->infos;
1189 
1190  infos->player_hundr_secs2 = (gint)infos->current_time % 100;
1191 
1192  gint tt2 = infos->total_time / 100;
1193  gfloat adj_position = (gint)gtk_adjustment_get_value(ui->gui->progress_adj);
1194  infos->current_time = (adj_position * tt2) / 100000;
1195 
1196  infos->player_seconds2 = (gint)infos->current_time % 60;
1197  infos->player_minutes2 = (gint)infos->current_time / 60;
1198 
1199  infos->current_time = get_elapsed_time(ui);
1200 
1202 }
1203 
1205 static gboolean progress_bar_scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
1206 {
1207  return FALSE;
1208 }
1209 
1211 static gboolean progress_bar_enter_event(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
1212 {
1213  return FALSE;
1214 }
1215 
1217 static gboolean progress_bar_leave_event(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
1218 {
1219  return FALSE;
1220 }
1221 
1223 static GtkWidget *create_song_bar_hbox(ui_state *ui)
1224 {
1225  GtkAdjustment *progress_adj =
1226  GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 100001.0, 0, 10000, 1000));
1227  ui->gui->progress_adj = progress_adj;
1228 
1229  GtkWidget *progress_bar = wh_hscale_new(progress_adj);
1230  ui->gui->progress_bar = progress_bar;
1231  g_object_set(progress_bar, "draw-value", FALSE, NULL);
1232 
1233  g_signal_connect(G_OBJECT(progress_bar), "button-press-event",
1234  G_CALLBACK(progress_bar_click_event), ui);
1235  g_signal_connect(G_OBJECT(progress_bar), "button-release-event",
1236  G_CALLBACK(progress_bar_unclick_event), ui);
1237  g_signal_connect(G_OBJECT(progress_bar), "value-changed",
1238  G_CALLBACK(progress_bar_value_changed_event), ui);
1239 
1240  g_signal_connect(G_OBJECT(progress_bar), "enter-notify-event",
1241  G_CALLBACK(progress_bar_enter_event), NULL);
1242  g_signal_connect(G_OBJECT(progress_bar), "leave-notify-event",
1243  G_CALLBACK(progress_bar_leave_event), NULL);
1244  g_signal_connect(G_OBJECT(progress_bar), "scroll-event",
1245  G_CALLBACK(progress_bar_scroll_event), NULL);
1246 
1247  gtk_widget_set_sensitive(GTK_WIDGET(progress_bar), FALSE);
1248 
1249  GtkWidget *song_bar_hbox = wh_hbox_new();
1250  gtk_box_pack_start(GTK_BOX(song_bar_hbox), progress_bar, TRUE, TRUE, 5);
1251  return song_bar_hbox;
1252 }
1253 
1255 static void print_about_the_song(ui_state *ui)
1256 {
1257  gchar total_infos[512];
1258  player_get_song_infos(total_infos, ui);
1259 
1260  gtk_label_set_text(GTK_LABEL(ui->gui->song_infos), total_infos);
1261 }
1262 
1264 static void print_player_filename(ui_state *ui)
1265 {
1266  gchar *fname = player_get_filename(ui);
1267  if (fname != NULL)
1268  {
1269  if (strcmp(fname, "disconnect"))
1270  {
1271  change_current_filename(fname, ui);
1272  }
1273  g_free(fname);
1274  }
1275 
1276  gchar *title = player_get_title(ui);
1277  if (title != NULL)
1278  {
1279  gtk_label_set_text(GTK_LABEL(ui->gui->song_name_label), title);
1280  g_free(title);
1281  }
1282 }
1283 
1288 static void print_all_song_infos(ui_state *ui)
1289 {
1290  print_about_the_song(ui);
1291  print_player_filename(ui);
1292 }
1293 
1300 static void print_song_time_elapsed(ui_state *ui)
1301 {
1302  gchar seconds[16], minutes[16], seconds_minutes[64];
1303 
1304  gint time = player_get_elapsed_time(ui);
1305  ui->infos->player_hundr_secs = (time % 1000) / 10;
1306 
1307  gint temp = (time/1000)/60;
1308  ui->infos->player_minutes = temp;
1309  ui->infos->player_seconds = (time/1000) - (temp*60);
1310 
1311  g_snprintf(minutes, 16, "%d", temp);
1312  g_snprintf(seconds, 16, "%d", (time/1000) - (temp*60));
1313 
1314  gchar total_seconds[16], total_minutes[16];
1315 
1316  gint tt = ui->infos->total_time * 10;
1317  temp = (tt / 1000) / 60;
1318 
1319  g_snprintf(total_minutes, 16, "%d", temp);
1320  g_snprintf(total_seconds, 16, "%d", (tt/1000) - (temp*60));
1321  g_snprintf(seconds_minutes, 64, "%s : %s / %s : %s",
1322  minutes, seconds, total_minutes, total_seconds);
1323 
1324  gtk_label_set_text(GTK_LABEL(ui->gui->label_time), seconds_minutes);
1325 }
1326 
1328 static void change_volume_button(ui_state *ui)
1329 {
1330  if (!player_is_running(ui))
1331  {
1332  return;
1333  }
1334 
1335  gint volume = player_get_volume(ui);
1336  if (volume < 0)
1337  {
1338  return;
1339  }
1340 
1341  gtk_scale_button_set_value(GTK_SCALE_BUTTON(ui->gui->volume_button), volume / 100.0);
1342 }
1343 
1344 void set_quick_preview_end_splitpoint_safe(gint value, ui_state *ui)
1345 {
1346  lock_mutex(&ui->variables_mutex);
1347  ui->status->quick_preview_end_splitpoint = value;
1348  unlock_mutex(&ui->variables_mutex);
1349 }
1350 
1351 gint get_quick_preview_end_splitpoint_safe(ui_state *ui)
1352 {
1353  lock_mutex(&ui->variables_mutex);
1354  gint quick_preview_end_splitpoint = ui->status->quick_preview_end_splitpoint;
1355  unlock_mutex(&ui->variables_mutex);
1356  return quick_preview_end_splitpoint;
1357 }
1358 
1360 static void change_progress_bar(ui_state *ui)
1361 {
1362  gui_status *status = ui->status;
1363  ui_infos *infos = ui->infos;
1364 
1365  if (!player_is_running(ui) || status->mouse_on_progress_bar)
1366  {
1367  refresh_drawing_area(ui->gui);
1368  return;
1369  }
1370 
1371  infos->total_time = player_get_total_time(ui) / 10;
1372 
1373  infos->current_time = infos->player_seconds * 100 +
1374  infos->player_minutes * 6000 +
1375  infos->player_hundr_secs;
1376 
1377  gdouble adj_position = (infos->current_time * 100000) / infos->total_time;
1378  gtk_adjustment_set_value(ui->gui->progress_adj, adj_position);
1379 
1380  infos->current_time = get_elapsed_time(ui);
1381 
1382  gint stop_splitpoint = get_splitpoint_time(get_quick_preview_end_splitpoint_safe(ui), ui);
1383  gint start_splitpoint = get_splitpoint_time(status->preview_start_splitpoint, ui);
1384  if ((stop_splitpoint < (gint)(infos->current_time-150)) ||
1385  (start_splitpoint > (gint)(infos->current_time+150)))
1386  {
1387  cancel_quick_preview(status);
1388  }
1389 }
1390 
1392 static GtkWidget *create_filename_player_hbox(gui_state *gui)
1393 {
1394  GtkWidget *song_name_label = gtk_label_new("");
1395  gtk_label_set_selectable(GTK_LABEL(song_name_label), TRUE);
1396  gui->song_name_label = song_name_label;
1397 
1398  g_object_set(G_OBJECT(song_name_label), "selectable", FALSE, NULL);
1399 
1400  gtk_label_set_ellipsize(GTK_LABEL(song_name_label), PANGO_ELLIPSIZE_END);
1401 
1402  GtkWidget *filename_player_hbox = wh_hbox_new();
1403 
1404 #if GTK_MAJOR_VERSION <= 2
1405  //ellipsize does not work as in gtk+2, so we show the label in the middle
1406  gtk_box_pack_start(GTK_BOX(filename_player_hbox), song_name_label,
1407  TRUE, TRUE, 15);
1408 #else
1409  gtk_box_pack_start(GTK_BOX(filename_player_hbox), song_name_label, FALSE, FALSE, 15);
1410 #endif
1411 
1412  return filename_player_hbox;
1413 }
1414 
1416 gfloat get_right_drawing_time(gfloat current_time, gfloat total_time, gfloat zoom_coeff)
1417 {
1418  gfloat right = total_time / zoom_coeff;
1419  gfloat center = right/2;
1420  gfloat offset = current_time - center;
1421  return right + offset;
1422 }
1423 
1425 gfloat get_left_drawing_time(gfloat current_time, gfloat total_time, gfloat zoom_coeff)
1426 {
1427  gfloat right = total_time / zoom_coeff;
1428  gfloat center = right/2;
1429  return current_time - center;
1430 }
1431 
1437 static gchar *get_time_for_drawing(gchar *str, gint time, gboolean hundr_or_not, gint *number_of_chars)
1438 {
1439  gint mins = time / 6000;
1440  gint secs = (time / 100) % 60;
1441 
1442  if (hundr_or_not)
1443  {
1444  gint hundr = time % 100;
1445  *number_of_chars = g_snprintf(str, 30, "%d:%02d:%02d", mins, secs, hundr);
1446  }
1447  else
1448  {
1449  *number_of_chars = g_snprintf(str, 30, "%d:%02d", mins, secs);
1450  }
1451 
1452  return str;
1453 }
1454 
1455 //transform pixels to time
1456 static gfloat pixels_to_time(gfloat width, gint pixels, ui_state *ui)
1457 {
1458  return (ui->infos->total_time * (gfloat)pixels)/(width * ui->infos->zoom_coeff);
1459 }
1460 
1461 static gint time_to_pixels(gint width, gfloat time, gfloat total_time, gfloat zoom_coeff)
1462 {
1463  return (width * time * zoom_coeff) / total_time;
1464 }
1465 
1471 static gint convert_time_to_pixels(gint width, gfloat time,
1472  gfloat current_time, gfloat total_time, gfloat zoom_coeff)
1473 {
1474  return width/2 + time_to_pixels(width, time - current_time, total_time, zoom_coeff);
1475 }
1476 
1477 static void draw_motif(GtkWidget *da, cairo_t *gc, gint ylimit, gint x, gint time_interval)
1478 {
1479  GdkColor color;
1480  switch (time_interval)
1481  {
1482  case HUNDR_SECONDS:
1483  color.red = 65000;color.green = 0;color.blue = 0;
1484  break;
1485  case TENS_OF_SECONDS:
1486  color.red = 0;color.green = 0;color.blue = 65000;
1487  break;
1488  case SECONDS:
1489  color.red = 0;color.green = 65000;color.blue = 0;
1490  break;
1491  case TEN_SECONDS:
1492  color.red = 65000;color.green = 0;color.blue = 40000;
1493  break;
1494  case MINUTES:
1495  color.red = 1000;color.green = 10000;color.blue = 65000;
1496  break;
1497  case TEN_MINUTES:
1498  color.red = 65000;color.green = 0;color.blue = 0;
1499  break;
1500  case HOURS:
1501  color.red = 0;color.green = 0;color.blue = 0;
1502  break;
1503  default:
1504  break;
1505  }
1506 
1507  dh_set_color(gc, &color);
1508 
1509  draw_point(gc, x, ylimit+6);
1510  draw_point(gc, x, ylimit+7);
1511  draw_point(gc, x, ylimit+8);
1512  draw_point(gc, x-1, ylimit+8);
1513  draw_point(gc, x+1, ylimit+8);
1514  draw_point(gc, x, ylimit+9);
1515  draw_point(gc, x-1, ylimit+9);
1516  draw_point(gc, x+1, ylimit+9);
1517  draw_point(gc, x-2, ylimit+9);
1518  draw_point(gc, x+2, ylimit+9);
1519  draw_point(gc, x-3, ylimit+9);
1520  draw_point(gc, x+3, ylimit+9);
1521  draw_point(gc, x, ylimit+10);
1522  draw_point(gc, x-1, ylimit+10);
1523  draw_point(gc, x+1, ylimit+10);
1524  draw_point(gc, x-2, ylimit+10);
1525  draw_point(gc, x+2, ylimit+10);
1526  draw_point(gc, x-3, ylimit+10);
1527  draw_point(gc, x+3, ylimit+10);
1528 
1529  cairo_stroke(gc);
1530 }
1531 
1533 static void draw_marks(gint time_interval, gint left_mark,
1534  gint right_mark, gint ylimit, GtkWidget *da, cairo_t *gc, ui_state *ui)
1535 {
1536  gint left2 = (left_mark / time_interval) * time_interval;
1537  if (left2 < left_mark)
1538  {
1539  left2 += time_interval;
1540  }
1541 
1542  gint i;
1543  gint i_pixel;
1544  for (i = left2; i <= right_mark; i += time_interval)
1545  {
1546  i_pixel = convert_time_to_pixels(ui->infos->width_drawing_area, i,
1547  ui->infos->current_time, ui->infos->total_time, ui->infos->zoom_coeff);
1548 
1549  draw_motif(da, gc, ylimit, i_pixel, time_interval);
1550  }
1551 }
1552 
1555 {
1556  cancel_quick_preview(ui->status);
1557  set_quick_preview_end_splitpoint_safe(-1, ui);
1558  ui->status->preview_start_splitpoint = -1;
1559 }
1560 
1563 {
1564  status->quick_preview = FALSE;
1565 }
1566 
1575 static void draw_motif_splitpoints(GtkWidget *da, cairo_t *gc,
1576  gint x, gint draw, gint current_point_hundr_secs,
1577  gboolean move, gint number_splitpoint, ui_state *ui)
1578 {
1579  int m = ui->gui->margin - 1;
1580 
1581  Split_point point = g_array_index(ui->splitpoints, Split_point, number_splitpoint);
1582  gboolean splitpoint_checked = point.checked;
1583 
1584  GdkColor color;
1585  color.red = 255 * 212; color.green = 255 * 100; color.blue = 255 * 200;
1586  dh_set_color(gc, &color);
1587 
1588  //if it' the splitpoint we move, don't fill in the circle and the square
1589  if (!draw)
1590  {
1591  dh_draw_rectangle(gc, FALSE, x-6,4, 11,11);
1592  }
1593  else
1594  {
1595  dh_draw_rectangle(gc, TRUE, x-6,4, 12,12);
1596 
1597  if (number_splitpoint == get_first_splitpoint_selected(ui->gui))
1598  {
1599  color.red = 255 * 220; color.green = 255 * 220; color.blue = 255 * 255;
1600  dh_set_color(gc, &color);
1601 
1602  dh_draw_rectangle(gc, TRUE, x-4,6, 8,8);
1603  }
1604  }
1605 
1606  color.red = 255 * 212; color.green = 255 * 196; color.blue = 255 * 221;
1607  dh_set_color(gc, &color);
1608 
1609  gint i = 0;
1610  for(i = 0;i < 5;i++)
1611  {
1612  draw_point(gc, x+i, ui->gui->erase_split_ylimit + m + 3);
1613  draw_point(gc, x-i, ui->gui->erase_split_ylimit + m + 3);
1614  draw_point(gc, x+i, ui->gui->erase_split_ylimit + m + 4);
1615  draw_point(gc, x-i, ui->gui->erase_split_ylimit + m + 4);
1616  }
1617  cairo_stroke(gc);
1618 
1619  if (move)
1620  {
1621  if (splitpoint_checked)
1622  {
1623  color.red = 15000;color.green = 40000;color.blue = 25000;
1624  }
1625  else
1626  {
1627  color.red = 25000;color.green = 25000;color.blue = 40000;
1628  }
1629  dh_set_color(gc, &color);
1630 
1631  dh_draw_line(gc, x, ui->gui->erase_split_ylimit + m -8, x, ui->gui->progress_ylimit + m, TRUE, TRUE);
1632  }
1633 
1634  color.red = 255 * 22; color.green = 255 * 35; color.blue = 255 * 91;
1635  dh_set_color(gc, &color);
1636 
1637  //draw the splitpoint motif
1638  for (i = -3;i <= 1;i++)
1639  {
1640  draw_point(gc, x, ui->gui->erase_split_ylimit + m +i);
1641  }
1642  for (i = 2;i <= 5;i++)
1643  {
1644  draw_point(gc, x, ui->gui->erase_split_ylimit + m + i);
1645  }
1646  for (i = 3;i <= 4;i++)
1647  {
1648  draw_point(gc, x-1, ui->gui->erase_split_ylimit + m + i);
1649  draw_point(gc, x+1, ui->gui->erase_split_ylimit + m + i);
1650  }
1651  for (i = 6;i <= 11;i++)
1652  {
1653  draw_point(gc, x, ui->gui->erase_split_ylimit + m + i);
1654  }
1655 
1656  //bottom splitpoint vertical bar
1657  for (i = 0;i < ui->gui->margin;i++)
1658  {
1659  draw_point(gc, x, ui->gui->progress_ylimit + m - i);
1660  }
1661 
1662  //bottom checkbox vertical bar
1663  for (i = 0;i < ui->gui->margin;i++)
1664  {
1665  draw_point(gc, x, ui->gui->splitpoint_ypos + m - i - 1);
1666  }
1667  cairo_stroke(gc);
1668 
1669  //bottom rectangle
1670  dh_set_color(gc, &color);
1671  color.red = 25000;color.green = 25000;color.blue = 25000;
1672  dh_draw_rectangle(gc, FALSE, x-6, ui->gui->splitpoint_ypos + m, 12,12);
1673 
1674  //draw a cross with 2 lines if the splitpoint is checked
1675  if (splitpoint_checked)
1676  {
1677  gint left = x - 6;
1678  gint right = x + 6;
1679  gint top = ui->gui->splitpoint_ypos + m;
1680  gint bottom = ui->gui->splitpoint_ypos + m + 12;
1681  dh_draw_line(gc, left, top, right, bottom, FALSE, TRUE);
1682  dh_draw_line(gc, left, bottom, right, top, FALSE, TRUE);
1683  }
1684 
1685  //-if the splitpoint is checked, set green color
1686  if (splitpoint_checked)
1687  {
1688  color.red = 15000;color.green = 40000;color.blue = 25000;
1689  }
1690  else
1691  {
1692  color.red = 25000;color.green = 25000;color.blue = 40000;
1693  }
1694  dh_set_color(gc, &color);
1695 
1696  dh_draw_arc(gc, FALSE, x, ui->gui->progress_ylimit + m+ 1 + 7, 14 / 2, 0, 2 * G_PI);
1697 
1698  //only fill the circle if we don't move that splitpoint
1699  if (draw)
1700  {
1701  dh_draw_arc(gc, TRUE, x, ui->gui->progress_ylimit + m + 1 + 8, 16 / 2, 0, 2 * G_PI);
1702  }
1703 
1704  if (draw)
1705  {
1706  gint number_of_chars = 0;
1707  gchar str[30] = { '\0' };
1708  get_time_for_drawing(str, current_point_hundr_secs, TRUE, &number_of_chars);
1709  dh_draw_text(gc, str, x - (number_of_chars * 3), ui->gui->checkbox_ypos + ui->gui->margin - 1);
1710  }
1711 
1712  if (ui->status->show_silence_wave)
1713  {
1714  color.red = 0;color.green = 0;color.blue = 0;
1715  dh_set_color(gc, &color);
1716  dh_draw_line(gc, x,ui->gui->text_ypos + ui->gui->margin, x,ui->gui->wave_ypos, move, TRUE);
1717  }
1718 }
1719 
1721 static void draw_splitpoints(gint left_mark, gint right_mark, GtkWidget *da, cairo_t *gc,
1722  ui_state *ui)
1723 {
1724  gint i = 0;
1725  for(i = 0; i < ui->infos->splitnumber; i++ )
1726  {
1727  gint current_point_hundr_secs = get_splitpoint_time(i, ui);
1728  if ((current_point_hundr_secs <= right_mark) &&
1729  (current_point_hundr_secs >= left_mark))
1730  {
1731  gint split_pixel =
1732  convert_time_to_pixels(ui->infos->width_drawing_area, current_point_hundr_secs,
1733  ui->infos->current_time, ui->infos->total_time, ui->infos->zoom_coeff);
1734 
1735  //the splitpoint that we move, draw it differently
1736  gboolean draw = TRUE;
1737  if (ui->status->splitpoint_to_move == i)
1738  {
1739  draw = FALSE;
1740  }
1741 
1742  draw_motif_splitpoints(da, gc, split_pixel, draw, current_point_hundr_secs, FALSE, i, ui);
1743  }
1744  }
1745 }
1746 
1747 static gint get_silence_filtered_presence_index(gfloat draw_time, ui_infos *infos)
1748 {
1749  //num_of_points_coeff_f : ogg ~= 1, mp3 ~= 4
1750  gfloat num_of_points_coeff_f =
1751  ceil((infos->number_of_silence_points / infos->total_time) * 10);
1752  gint num_of_points_coeff = (gint)num_of_points_coeff_f;
1753 
1754  if (draw_time > infos->fourty_minutes_time)
1755  {
1756  if (num_of_points_coeff < 3)
1757  {
1758  return 2;
1759  }
1760  return 4;
1761  }
1762 
1763  if (draw_time > infos->twenty_minutes_time)
1764  {
1765  if (num_of_points_coeff < 3)
1766  {
1767  return 1;
1768  }
1769  return 3;
1770  }
1771 
1772  if (draw_time > infos->ten_minutes_time)
1773  {
1774  if (num_of_points_coeff < 3)
1775  {
1776  return 0;
1777  }
1778  return 2;
1779  }
1780 
1781  if (draw_time > infos->six_minutes_time)
1782  {
1783  if (num_of_points_coeff < 3)
1784  {
1785  return -1;
1786  }
1787  return 1;
1788  }
1789 
1790  if (draw_time > infos->three_minutes_time)
1791  {
1792  if (num_of_points_coeff < 3)
1793  {
1794  return -1;
1795  }
1796  return 0;
1797  }
1798 
1799  return -1;
1800 }
1801 
1802 static gint point_is_filtered(gint index, gint filtered_index, ui_infos *infos)
1803 {
1804  if (!infos->filtered_points_presence)
1805  {
1806  return TRUE;
1807  }
1808 
1809  GArray *points_presence = g_ptr_array_index(infos->filtered_points_presence, filtered_index);
1810  return !g_array_index(points_presence, gint, index);
1811 }
1812 
1813 static gint adjust_filtered_index_according_to_number_of_points(gint filtered_index,
1814  gint left_mark, gint right_mark, ui_state *ui)
1815 {
1816  ui_infos *infos = ui->infos;
1817 
1818  if (filtered_index == 4)
1819  {
1820  return filtered_index;
1821  }
1822 
1823  gint number_of_points = 0;
1824  gint number_of_filtered_points = 0;
1825 
1826  gint i = 0;
1827  for (i = 0;i < infos->number_of_silence_points;i++)
1828  {
1829  long time = infos->silence_points[i].time;
1830  if ((time > right_mark) || (time < left_mark))
1831  {
1832  continue;
1833  }
1834 
1835  if (filtered_index >= 0 && point_is_filtered(i, filtered_index, infos))
1836  {
1837  number_of_filtered_points++;
1838  }
1839 
1840  number_of_points++;
1841  }
1842 
1843  if (number_of_points <= ui->infos->silence_wave_number_of_points_threshold)
1844  {
1845  return -1;
1846  }
1847 
1848  if (number_of_points - number_of_filtered_points > ui->infos->silence_wave_number_of_points_threshold)
1849  {
1850  return filtered_index + 1;
1851  }
1852 
1853  return filtered_index;
1854 }
1855 
1857 gint draw_silence_wave(gint left_mark, gint right_mark,
1858  gint interpolation_text_x, gint interpolation_text_y,
1859  gfloat draw_time, gint width_drawing_area, gint y_margin,
1860  gfloat current_time, gfloat total_time, gfloat zoom_coeff,
1861  GtkWidget *da, cairo_t *gc, ui_state *ui)
1862 {
1863  if (ui->status->currently_compute_douglas_peucker_filters ||
1864  get_currently_scanning_for_silence_safe(ui))
1865  {
1866  return -1;
1867  }
1868 
1869  GdkColor color;
1870 
1871  if (!ui->infos->silence_points)
1872  {
1873  color.red = 0;color.green = 0;color.blue = 0;
1874  dh_set_color(gc, &color);
1875  dh_draw_text_with_size(gc,_("No available wave"),
1876  interpolation_text_x, interpolation_text_y, 13);
1877  return -1;
1878  }
1879 
1880  double dashes[] = { 1.0, 3.0 };
1881  cairo_set_dash(gc, dashes, 0, 0.0);
1882  cairo_set_line_width(gc, 1.0);
1883  cairo_set_line_cap(gc, CAIRO_LINE_CAP_ROUND);
1884 
1885  color.red = 0;color.green = 0;color.blue = 0;
1886  dh_set_color(gc, &color);
1887 
1888  gint first_time = SPLT_TRUE;
1889 
1890  gint filtered_index = get_silence_filtered_presence_index(draw_time, ui->infos);
1891  gint interpolation_level =
1892  adjust_filtered_index_according_to_number_of_points(filtered_index,
1893  left_mark, right_mark, ui);
1894 
1895  gint stroke_counter = 0;
1896 
1897  gint i = 0;
1898  for (i = 0;i < ui->infos->number_of_silence_points;i++)
1899  {
1900  if (interpolation_level >= 0 && point_is_filtered(i, interpolation_level, ui->infos))
1901  {
1902  continue;
1903  }
1904 
1905  long time = ui->infos->silence_points[i].time;
1906  if ((time > right_mark) || (time < left_mark))
1907  {
1908  continue;
1909  }
1910 
1911  float level = ui->infos->silence_points[i].level;
1912 
1913  gint x = convert_time_to_pixels(width_drawing_area,
1914  (gfloat)time, current_time, total_time, zoom_coeff);
1915  gint y = y_margin + (gint)floorf(level);
1916 
1917  if (first_time)
1918  {
1919  cairo_move_to(gc, x, y);
1920  first_time = SPLT_FALSE;
1921  }
1922  else
1923  {
1924  cairo_line_to(gc, x, y);
1925  }
1926 
1927  stroke_counter++;
1928  if (stroke_counter % 4 == 0)
1929  {
1930  cairo_stroke(gc);
1931  cairo_move_to(gc, x, y);
1932  }
1933  }
1934 
1935  cairo_stroke(gc);
1936 
1937  color.red = 0;color.green = 0;color.blue = 0;
1938  dh_set_color(gc, &color);
1939 
1940  if (interpolation_level < 0)
1941  {
1942  dh_draw_text_with_size(gc,_("No wave interpolation"),
1943  interpolation_text_x, interpolation_text_y, 13);
1944  }
1945  else
1946  {
1947  gchar interpolation_text[128] = { '\0' };
1948  g_snprintf(interpolation_text, 128, _("Wave interpolation level %d"), interpolation_level + 1);
1949  dh_draw_text_with_size(gc, interpolation_text, interpolation_text_x, interpolation_text_y, 13);
1950  }
1951 
1952  return interpolation_level;
1953 }
1954 
1955 static void draw_rectangles_between_splitpoints(cairo_t *cairo_surface, ui_state *ui)
1956 {
1957  GdkColor color;
1958 
1959  //yellow small rectangle
1960  gint point_time_left = -1;
1961  gint point_time_right = -1;
1962  get_current_splitpoints_time_left_right(&point_time_left, &point_time_right, NULL, ui);
1963  color.red = 255 * 255;color.green = 255 * 255;color.blue = 255 * 210;
1964  draw_small_rectangle(point_time_left, point_time_right, color, cairo_surface, ui);
1965 
1966  gint gray_factor = 210;
1967  color.red = 255 * gray_factor;color.green = 255 * gray_factor;color.blue = 255 * gray_factor;
1968 
1969  //gray areas
1970  if (ui->infos->splitnumber == 0)
1971  {
1972  draw_small_rectangle(0, ui->infos->total_time, color, cairo_surface, ui);
1973  return;
1974  }
1975 
1976  draw_small_rectangle(0, get_splitpoint_time(0, ui), color, cairo_surface, ui);
1977  draw_small_rectangle(get_splitpoint_time(ui->infos->splitnumber-1, ui), ui->infos->total_time,
1978  color, cairo_surface, ui);
1979  gint i = 0;
1980  for (i = 0; i < ui->infos->splitnumber - 1; i++ )
1981  {
1982  Split_point point = g_array_index(ui->splitpoints, Split_point, i);
1983  if (!point.checked)
1984  {
1985  gint left_time = get_splitpoint_time(i, ui);
1986  gint right_time = get_splitpoint_time(i+1, ui);
1987  draw_small_rectangle(left_time, right_time, color, cairo_surface, ui);
1988  }
1989  }
1990 }
1991 
1992 #if GTK_MAJOR_VERSION <= 2
1993 static gboolean da_draw_event(GtkWidget *da, GdkEventExpose *event, ui_state *ui)
1994 {
1995  cairo_t *gc = gdk_cairo_create(da->window);
1996 #else
1997 static gboolean da_draw_event(GtkWidget *da, cairo_t *gc, ui_state *ui)
1998 {
1999 #endif
2000 
2001  ui_infos *infos = ui->infos;
2002  gui_state *gui = ui->gui;
2003  gui_status *status = ui->status;
2004 
2005 #ifdef __WIN32__
2006  if ((status->playing || status->timer_active) &&
2007  get_process_in_progress_safe(ui))
2008  {
2009  GdkColor mycolor;
2010  mycolor.red = 255 * 0; mycolor.green = 255 * 0; mycolor.blue = 255 * 255;
2011  dh_set_color(gc, &mycolor);
2012  dh_draw_text_with_size(gc, _(" Please wait for the process to finish ..."),
2013  30, gui->margin - 3, 13);
2014 
2015  return TRUE;
2016  }
2017 #endif
2018 
2019  set_process_in_progress_safe(TRUE, ui);
2020 
2021  if (gui->drawing_area_expander != NULL &&
2022  !gtk_expander_get_expanded(GTK_EXPANDER(gui->drawing_area_expander)))
2023  {
2024  set_process_in_progress_safe(FALSE, ui);
2025  return TRUE;
2026  }
2027 
2028  //on a slow hardware, this improves a lot the computing performance
2029  if (status->currently_compute_douglas_peucker_filters)
2030  {
2031  GdkColor mycolor;
2032  mycolor.red = 255 * 0; mycolor.green = 255 * 0; mycolor.blue = 255 * 255;
2033  dh_set_color(gc, &mycolor);
2034  dh_draw_text_with_size(gc, _(" Please wait ... currently computing Douglas Peucker filters."),
2035  30, gui->margin - 3, 13);
2036 
2037  set_process_in_progress_safe(FALSE, ui);
2038  return TRUE;
2039  }
2040 
2041  gint old_width_drawing_area = infos->width_drawing_area;
2042 
2043  int width = 0, height = 0;
2044  wh_get_widget_size(da, &width, &height);
2045  if (status->show_silence_wave)
2046  {
2047  if (height != DRAWING_AREA_HEIGHT_WITH_SILENCE_WAVE)
2048  {
2049  gtk_widget_set_size_request(da, DRAWING_AREA_WIDTH, DRAWING_AREA_HEIGHT_WITH_SILENCE_WAVE);
2050  }
2051  }
2052  else
2053  {
2054  if (height != DRAWING_AREA_HEIGHT)
2055  {
2056  gtk_widget_set_size_request(da, DRAWING_AREA_WIDTH, DRAWING_AREA_HEIGHT);
2057  }
2058  }
2059 
2060  gint real_progress_length = 26;
2061  gint real_text_length = 12;
2062 
2063  gint erase_splitpoint_length = gui->real_erase_split_length + (gui->margin * 2);
2064  gint progress_length = real_progress_length + gui->margin;
2065  gint move_split_length = gui->real_move_split_length + gui->margin;
2066  gint text_length = real_text_length + gui->margin;
2067  gint checkbox_length = gui->real_checkbox_length + gui->margin;
2068  gint wave_length = gui->real_wave_length + gui->margin;
2069 
2070  //
2071  gui->erase_split_ylimit = erase_splitpoint_length;
2072  gui->progress_ylimit = gui->erase_split_ylimit + progress_length;
2073  gui->splitpoint_ypos = gui->progress_ylimit + move_split_length;
2074  gui->checkbox_ypos = gui->splitpoint_ypos + checkbox_length;
2075  gui->text_ypos = gui->checkbox_ypos + text_length + gui->margin;
2076  gui->wave_ypos = gui->text_ypos + wave_length + gui->margin;
2077 
2078  gint bottom_left_middle_right_text_ypos = gui->text_ypos;
2079  if (status->show_silence_wave)
2080  {
2081  bottom_left_middle_right_text_ypos = gui->wave_ypos;
2082  }
2083 
2084  gint nbr_chars = 0;
2085 
2086  wh_get_widget_size(da, &infos->width_drawing_area, NULL);
2087 
2088  if (infos->width_drawing_area != old_width_drawing_area)
2089  {
2090  refresh_preview_drawing_areas(gui);
2091  }
2092 
2093  GdkColor color;
2094  color.red = 255 * 235;color.green = 255 * 235; color.blue = 255 * 235;
2095  dh_set_color(gc, &color);
2096 
2097  //background rectangle
2098  dh_draw_rectangle(gc, TRUE, 0,0, infos->width_drawing_area, gui->wave_ypos + text_length + 2);
2099 
2100  color.red = 255 * 255;color.green = 255 * 255;color.blue = 255 * 255;
2101  dh_set_color(gc, &color);
2102 
2103  //background white rectangles
2104  dh_draw_rectangle(gc, TRUE, 0, gui->margin, infos->width_drawing_area, gui->real_erase_split_length);
2105  dh_draw_rectangle(gc, TRUE, 0, gui->erase_split_ylimit, infos->width_drawing_area, progress_length);
2106  dh_draw_rectangle(gc, TRUE, 0, gui->progress_ylimit+gui->margin, infos->width_drawing_area, gui->real_move_split_length);
2107  dh_draw_rectangle(gc, TRUE, 0, gui->splitpoint_ypos+gui->margin, infos->width_drawing_area, gui->real_checkbox_length);
2108  dh_draw_rectangle(gc, TRUE, 0, gui->checkbox_ypos+gui->margin, infos->width_drawing_area, text_length);
2109  if (status->show_silence_wave)
2110  {
2111  dh_draw_rectangle(gc, TRUE, 0, gui->text_ypos + gui->margin, infos->width_drawing_area, wave_length);
2112  }
2113 
2114  if (!status->playing || !status->timer_active)
2115  {
2116  color.red = 255 * 212; color.green = 255 * 100; color.blue = 255 * 200;
2117  dh_set_color(gc, &color);
2118  dh_draw_text(gc, _(" left click on splitpoint selects it, right click erases it"),
2119  0, gui->margin - 3);
2120 
2121  color.red = 0;color.green = 0;color.blue = 0;
2122  dh_set_color(gc, &color);
2123  dh_draw_text(gc, _(" left click + move changes song position, right click + move changes zoom"),
2124  0, gui->erase_split_ylimit + gui->margin);
2125 
2126  color.red = 15000;color.green = 40000;color.blue = 25000;
2127  dh_set_color(gc, &color);
2128  dh_draw_text(gc,
2129  _(" left click on point + move changes point position, right click play preview"),
2130  0, gui->progress_ylimit + gui->margin);
2131 
2132  color.red = 0; color.green = 0; color.blue = 0;
2133  dh_set_color(gc, &color);
2134  dh_draw_text(gc, _(" left click on rectangle checks/unchecks 'keep splitpoint'"),
2135  0, gui->splitpoint_ypos + 1);
2136 
2137  set_process_in_progress_safe(FALSE, ui);
2138  return TRUE;
2139  }
2140 
2141  gfloat left_time = get_left_drawing_time(infos->current_time, infos->total_time, infos->zoom_coeff);
2142  gfloat right_time = get_right_drawing_time(infos->current_time, infos->total_time, infos->zoom_coeff);
2143 
2144  //marks to draw seconds, minutes...
2145  gint left_mark = (gint)left_time;
2146  gint right_mark = (gint)right_time;
2147  if (left_mark < 0)
2148  {
2149  left_mark = 0;
2150  }
2151  if (right_mark > infos->total_time)
2152  {
2153  right_mark = (gint)infos->total_time;
2154  }
2155 
2156  gfloat total_draw_time = right_time - left_time;
2157 
2158  gchar str[30] = { '\0' };
2159  gint beg_pixel = convert_time_to_pixels(infos->width_drawing_area, 0,
2160  infos->current_time, infos->total_time, infos->zoom_coeff);
2161 
2162  draw_rectangles_between_splitpoints(gc, ui);
2163 
2164  //blue color
2165  color.red = 255 * 150; color.green = 255 * 150; color.blue = 255 * 255;
2166  dh_set_color(gc, &color);
2167 
2168  //if it's the first splitpoint from play preview
2169  if (get_quick_preview_end_splitpoint_safe(ui) != -1)
2170  {
2171  gint right_pixel =
2172  convert_time_to_pixels(infos->width_drawing_area,
2173  get_splitpoint_time(get_quick_preview_end_splitpoint_safe(ui), ui),
2174  infos->current_time, infos->total_time, infos->zoom_coeff);
2175  gint left_pixel =
2176  convert_time_to_pixels(infos->width_drawing_area,
2177  get_splitpoint_time(status->preview_start_splitpoint, ui),
2178  infos->current_time, infos->total_time, infos->zoom_coeff);
2179 
2180  gint preview_splitpoint_length = right_pixel - left_pixel + 1;
2181 
2182  //top buttons
2183  dh_draw_rectangle(gc, TRUE, left_pixel, gui->progress_ylimit-2, preview_splitpoint_length, 3);
2184 
2185  //for quick preview, put red bar
2186  if (status->quick_preview)
2187  {
2188  color.red = 255 * 255;color.green = 255 * 160;color.blue = 255 * 160;
2189  dh_set_color(gc, &color);
2190  dh_draw_rectangle(gc, TRUE, left_pixel, gui->erase_split_ylimit, preview_splitpoint_length, 3);
2191  }
2192  }
2193  else
2194  {
2195  //if we draw until the end
2196  if ((status->preview_start_splitpoint != -1) &&
2197  (status->preview_start_splitpoint != (infos->splitnumber-1)))
2198  {
2199  gint left_pixel =
2200  convert_time_to_pixels(infos->width_drawing_area,
2201  get_splitpoint_time(status->preview_start_splitpoint, ui),
2202  infos->current_time, infos->total_time, infos->zoom_coeff);
2203  dh_draw_rectangle(gc, TRUE, left_pixel, gui->progress_ylimit-2, infos->width_drawing_area-left_pixel, 3);
2204 
2205  //red bar quick preview
2206  if (status->quick_preview)
2207  {
2208  color.red = 255 * 255;color.green = 255 * 160;color.blue = 255 * 160;
2209  dh_set_color(gc, &color);
2210  dh_draw_rectangle(gc, TRUE, left_pixel, gui->erase_split_ylimit, infos->width_drawing_area-left_pixel, 3);
2211  }
2212  }
2213  }
2214 
2215  //song start
2216  if (left_time <= 0)
2217  {
2218  color.red = 255 * 235;color.green = 255 * 235; color.blue = 255 * 235;
2219  dh_set_color(gc, &color);
2220  dh_draw_rectangle(gc, TRUE, 0,0, beg_pixel, gui->wave_ypos);
2221  }
2222  else
2223  {
2224  color.red = 30000;color.green = 0;color.blue = 30000;
2225  dh_set_color(gc, &color);
2226 
2227  get_time_for_drawing(str, left_time, FALSE, &nbr_chars);
2228  dh_draw_text(gc, str, 15, bottom_left_middle_right_text_ypos);
2229  }
2230 
2231  gint end_pixel =
2232  convert_time_to_pixels(infos->width_drawing_area, infos->total_time,
2233  infos->current_time, infos->total_time, infos->zoom_coeff);
2234  //song end
2235  if (right_time >= infos->total_time)
2236  {
2237  color.red = 255 * 235;color.green = 255 * 235;color.blue = 255 * 235;
2238  dh_set_color(gc, &color);
2239  dh_draw_rectangle(gc, TRUE, end_pixel,0, infos->width_drawing_area, bottom_left_middle_right_text_ypos);
2240  }
2241  else
2242  {
2243  color.red = 30000;color.green = 0;color.blue = 30000;
2244  dh_set_color(gc, &color);
2245 
2246  get_time_for_drawing(str, right_time, FALSE, &nbr_chars);
2247  dh_draw_text(gc, str, infos->width_drawing_area - 52, bottom_left_middle_right_text_ypos);
2248  }
2249 
2250  if (total_draw_time < infos->hundr_secs_th)
2251  {
2252  draw_marks(HUNDR_SECONDS, left_mark, right_mark,
2253  gui->erase_split_ylimit + progress_length/4, da, gc, ui);
2254  }
2255  if (total_draw_time < infos->tens_of_secs_th)
2256  {
2257  draw_marks(TENS_OF_SECONDS, left_mark, right_mark,
2258  gui->erase_split_ylimit + progress_length/4, da, gc, ui);
2259  }
2260  if (total_draw_time < infos->secs_th)
2261  {
2262  draw_marks(SECONDS, left_mark, right_mark,
2263  gui->erase_split_ylimit + progress_length/4, da, gc, ui);
2264  }
2265  if (total_draw_time < infos->ten_secs_th)
2266  {
2267  draw_marks(TEN_SECONDS, left_mark, right_mark,
2268  gui->erase_split_ylimit + progress_length/4, da, gc, ui);
2269  }
2270  if (total_draw_time < infos->minutes_th)
2271  {
2272  draw_marks(MINUTES, left_mark, right_mark,
2273  gui->erase_split_ylimit + progress_length/4, da, gc, ui);
2274  }
2275  if (total_draw_time < infos->ten_minutes_th)
2276  {
2277  draw_marks(TEN_MINUTES, left_mark, right_mark,
2278  gui->erase_split_ylimit + progress_length/4, da, gc, ui);
2279  }
2280  draw_marks(HOURS, left_mark, right_mark,
2281  gui->erase_split_ylimit + progress_length/4, da, gc, ui);
2282 
2283  //draw mobile button1 position line
2284  if (status->button1_pressed)
2285  {
2286  gint move_pixel = convert_time_to_pixels(infos->width_drawing_area,
2287  status->move_time, infos->current_time,
2288  infos->total_time, infos->zoom_coeff);
2289 
2290  if (status->move_splitpoints)
2291  {
2292  draw_motif_splitpoints(da, gc, move_pixel,TRUE, status->move_time,
2293  TRUE, status->splitpoint_to_move, ui);
2294 
2295  color.red = 0;color.green = 0;color.blue = 0;
2296  dh_set_color(gc, &color);
2297 
2298  get_time_for_drawing(str, infos->current_time, FALSE, &nbr_chars);
2299  dh_draw_text(gc, str, infos->width_drawing_area/2-11, bottom_left_middle_right_text_ypos);
2300  }
2301  else
2302  {
2303  color.red = 255 * 255;color.green = 0;color.blue = 0;
2304  dh_set_color(gc, &color);
2305  dh_draw_line(gc, move_pixel, gui->erase_split_ylimit, move_pixel, gui->progress_ylimit, TRUE, TRUE);
2306 
2307  if (status->show_silence_wave)
2308  {
2309  dh_draw_line(gc, move_pixel, gui->text_ypos + gui->margin, move_pixel, gui->wave_ypos, TRUE, TRUE);
2310  }
2311 
2312  color.red = 0;color.green = 0;color.blue = 0;
2313  dh_set_color(gc, &color);
2314 
2315  get_time_for_drawing(str, status->move_time, FALSE, &nbr_chars);
2316  dh_draw_text(gc, str, infos->width_drawing_area/2-11, bottom_left_middle_right_text_ypos);
2317  }
2318  }
2319  else
2320  {
2321  color.red = 0;color.green = 0;color.blue = 0;
2322  dh_set_color(gc, &color);
2323 
2324  get_time_for_drawing(str, infos->current_time, FALSE, &nbr_chars);
2325  dh_draw_text(gc, str, infos->width_drawing_area/2-11, bottom_left_middle_right_text_ypos);
2326  }
2327 
2328  color.red = 255 * 255;color.green = 0;color.blue = 0;
2329  dh_set_color(gc, &color);
2330 
2331  //top middle line, current position
2332  dh_draw_line(gc, infos->width_drawing_area/2, gui->erase_split_ylimit,
2333  infos->width_drawing_area/2, gui->progress_ylimit, FALSE, TRUE);
2334 
2335  //silence wave
2336  if (status->show_silence_wave)
2337  {
2338  draw_silence_wave(left_mark, right_mark,
2339  infos->width_drawing_area/2 + 3, gui->wave_ypos - gui->margin * 4,
2340  total_draw_time,
2341  infos->width_drawing_area, gui->text_ypos + gui->margin,
2342  infos->current_time, infos->total_time, infos->zoom_coeff,
2343  da, gc, ui);
2344 
2345  //silence wave middle line
2346  color.red = 255 * 255;color.green = 0;color.blue = 0;
2347  dh_set_color(gc, &color);
2348  dh_draw_line(gc, infos->width_drawing_area/2, gui->text_ypos + gui->margin,
2349  infos->width_drawing_area/2, gui->wave_ypos, FALSE, TRUE);
2350  }
2351 
2352  draw_splitpoints(left_mark, right_mark, da, gc, ui);
2353 
2354 #if GTK_MAJOR_VERSION <= 2
2355  cairo_destroy(gc);
2356 #endif
2357 
2358  set_process_in_progress_safe(FALSE, ui);
2359 
2360  return TRUE;
2361 }
2362 
2363 static void draw_small_rectangle(gint time_left, gint time_right,
2364  GdkColor color, cairo_t *cairo_surface, ui_state *ui)
2365 {
2366  if (time_left == -1 || time_right == -1)
2367  {
2368  return;
2369  }
2370 
2371  gint pixels_left = convert_time_to_pixels(ui->infos->width_drawing_area, time_left,
2372  ui->infos->current_time, ui->infos->total_time, ui->infos->zoom_coeff);
2373  gint pixels_right = convert_time_to_pixels(ui->infos->width_drawing_area, time_right,
2374  ui->infos->current_time, ui->infos->total_time, ui->infos->zoom_coeff);
2375  gint pixels_length = pixels_right - pixels_left;
2376 
2377  dh_set_color(cairo_surface, &color);
2378  dh_draw_rectangle(cairo_surface, TRUE, pixels_left, ui->gui->erase_split_ylimit,
2379  pixels_length, ui->gui->progress_ylimit - ui->gui->erase_split_ylimit+1);
2380 
2381  if (ui->status->show_silence_wave)
2382  {
2383  dh_draw_rectangle(cairo_surface, TRUE, pixels_left, ui->gui->text_ypos + ui->gui->margin,
2384  pixels_length, ui->gui->real_wave_length + ui->gui->margin);
2385  }
2386 }
2387 
2388 void get_current_splitpoints_time_left_right(gint *time_left, gint *time_right,
2389  gint *splitpoint_left, ui_state *ui)
2390 {
2391  ui_infos *infos = ui->infos;
2392 
2393  gint i = 0;
2394  for (i = 0; i < infos->splitnumber; i++ )
2395  {
2396  gint current_point_hundr_secs = get_splitpoint_time(i, ui);
2397  if (current_point_hundr_secs < infos->current_time - (DELTA * 2))
2398  {
2399  *time_left = current_point_hundr_secs;
2400  continue;
2401  }
2402 
2403  if (current_point_hundr_secs > infos->current_time + (DELTA * 2))
2404  {
2405  *time_right = current_point_hundr_secs;
2406  if (splitpoint_left != NULL) { *splitpoint_left = i; }
2407  break;
2408  }
2409  }
2410 
2411  if (splitpoint_left != NULL && *splitpoint_left == -1)
2412  {
2413  *splitpoint_left = infos->splitnumber;
2414  }
2415 }
2416 
2427 static gint get_splitpoint_clicked(gint button_y, gint type_clicked, gint type, ui_state *ui)
2428 {
2429  gint time_pos, time_right_pos;
2430  gint left_time = get_left_drawing_time(ui->infos->current_time, ui->infos->total_time, ui->infos->zoom_coeff);
2431 
2432  gint but_y;
2433  //click on a right button
2434  if (type_clicked != 3)
2435  {
2436  but_y = button_y;
2437  time_pos = left_time + pixels_to_time(ui->infos->width_drawing_area, ui->status->button_x, ui);
2438  }
2439  else
2440  {
2441  but_y = ui->status->button_y2;
2442  time_pos = left_time + pixels_to_time(ui->infos->width_drawing_area, ui->status->button_x2, ui);
2443  }
2444 
2445  //we get this to find time_right_pos - time_right
2446  //to see what time we have for X pixels
2447  gint pixels_to_look_for = ui->gui->real_erase_split_length / 2;
2448  if (type == 2)
2449  {
2450  pixels_to_look_for = ui->gui->real_move_split_length / 2;
2451  }
2452 
2453  if (type_clicked != 3)
2454  {
2455  time_right_pos = left_time +
2456  pixels_to_time(ui->infos->width_drawing_area, ui->status->button_x + pixels_to_look_for, ui);
2457  }
2458  else
2459  {
2460  time_right_pos = left_time +
2461  pixels_to_time(ui->infos->width_drawing_area, ui->status->button_x2 + pixels_to_look_for, ui);
2462  }
2463 
2464  //the time margin is the margin for the splitpoint,
2465  //where we can click at his left or right
2466  gint time_margin = time_right_pos - time_pos;
2467 
2468  gint margin1, margin2;
2469 
2470  if (type == 2)
2471  {
2472  margin1 = ui->gui->progress_ylimit + ui->gui->margin;
2473  margin2 = ui->gui->progress_ylimit + ui->gui->margin + ui->gui->real_move_split_length;
2474  }
2475  else if (type == 1)
2476  {
2477  margin1 = ui->gui->margin;
2478  margin2 = ui->gui->margin + ui->gui->real_erase_split_length;
2479  }
2480  else
2481  {
2482  margin1 = ui->gui->splitpoint_ypos + ui->gui->margin;
2483  margin2 = ui->gui->splitpoint_ypos + ui->gui->margin + ui->gui->real_checkbox_length;
2484  }
2485 
2486  //area outside the split move
2487  if ((but_y < margin1) || (but_y > margin2))
2488  {
2489  return -1;
2490  }
2491 
2492  gint i = 0;
2493  for(i = 0; i < ui->infos->splitnumber; i++ )
2494  {
2495  gint current_point_hundr_secs = get_splitpoint_time(i, ui);
2496  gint current_point_left = current_point_hundr_secs - time_margin;
2497  gint current_point_right = current_point_hundr_secs + time_margin;
2498 
2499  if ((time_pos >= current_point_left) && (time_pos <= current_point_right))
2500  {
2501  return i;
2502  }
2503  }
2504 
2505  return -1;
2506 }
2507 
2508 void set_preview_start_position_safe(gint value, ui_state *ui)
2509 {
2510  lock_mutex(&ui->variables_mutex);
2511  ui->status->preview_start_position = value;
2512  unlock_mutex(&ui->variables_mutex);
2513 }
2514 
2515 gint get_preview_start_position_safe(ui_state *ui)
2516 {
2517  lock_mutex(&ui->variables_mutex);
2518  gint preview_start_position = ui->status->preview_start_position;
2519  unlock_mutex(&ui->variables_mutex);
2520 
2521  return preview_start_position;
2522 }
2523 
2525 void player_quick_preview(gint splitpoint_to_preview, ui_state *ui)
2526 {
2527  if (splitpoint_to_preview == -1)
2528  {
2529  return;
2530  }
2531 
2532  gui_status *status = ui->status;
2533 
2534  set_preview_start_position_safe(get_splitpoint_time(splitpoint_to_preview, ui), ui);
2535  status->preview_start_splitpoint = splitpoint_to_preview;
2536 
2537  if (!player_is_playing(ui))
2538  {
2539  player_play(ui);
2540  usleep(50000);
2541  }
2542 
2543  if (player_is_paused(ui))
2544  {
2545  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->gui->pause_button), FALSE);
2546  }
2547 
2548  if (splitpoint_to_preview < ui->infos->splitnumber-1)
2549  {
2550  set_quick_preview_end_splitpoint_safe(splitpoint_to_preview + 1, ui);
2551  }
2552  else
2553  {
2554  set_quick_preview_end_splitpoint_safe(-1, ui);
2555  }
2556 
2557  player_seek(get_preview_start_position_safe(ui) * 10, ui);
2558  change_progress_bar(ui);
2559  put_status_message(_(" quick preview..."), ui);
2560 
2561  status->quick_preview = FALSE;
2562  if (get_quick_preview_end_splitpoint_safe(ui) != -1)
2563  {
2564  status->quick_preview = TRUE;
2565  }
2566 
2567  if (status->preview_start_splitpoint == (ui->infos->splitnumber-1))
2568  {
2570  }
2571 }
2572 
2574 static gboolean da_press_event(GtkWidget *da, GdkEventButton *event, ui_state *ui)
2575 {
2576  if (!ui->status->playing || !ui->status->timer_active)
2577  {
2578  return TRUE;
2579  }
2580 
2581  gui_status *status = ui->status;
2582  gui_state *gui = ui->gui;
2583  ui_infos *infos = ui->infos;
2584 
2585  //left click
2586  if (event->button == 1)
2587  {
2588  status->button_x = event->x;
2589  status->button_y = event->y;
2590  status->button1_pressed = TRUE;
2591 
2592  if ((status->button_y > gui->progress_ylimit + gui->margin) &&
2593  (status->button_y < gui->progress_ylimit + gui->margin + gui->real_move_split_length))
2594  {
2595  status->splitpoint_to_move = get_splitpoint_clicked(status->button_y, 1, 2, ui);
2596  if (status->splitpoint_to_move != -1)
2597  {
2598  status->move_splitpoints = TRUE;
2599  }
2600  }
2601  else
2602  {
2603  //area to remove a splitpoint
2604  if ((status->button_y > gui->margin) &&
2605  (status->button_y < gui->margin + gui->real_erase_split_length))
2606  {
2607  gint splitpoint_selected = get_splitpoint_clicked(status->button_y, 1, 1, ui);
2608  if (splitpoint_selected != -1)
2609  {
2610  status->select_splitpoints = TRUE;
2611  select_splitpoint(splitpoint_selected, gui);
2612  }
2613  refresh_drawing_area(gui);
2614  }
2615  else
2616  {
2617  //area to check a splitpoint
2618  if ((status->button_y > gui->splitpoint_ypos + gui->margin) &&
2619  (status->button_y < gui->splitpoint_ypos + gui->margin + gui->real_checkbox_length))
2620  {
2621  gint splitpoint_selected = get_splitpoint_clicked(status->button_y, 1, 3, ui);
2622  if (splitpoint_selected != -1)
2623  {
2624  status->check_splitpoint = TRUE;
2625  update_splitpoint_check(splitpoint_selected, ui);
2626  }
2627  refresh_drawing_area(gui);
2628  }
2629  }
2630  }
2631 
2632  if (!status->move_splitpoints)
2633  {
2634  status->move_time = infos->current_time;
2635  }
2636  else
2637  {
2638  status->move_time = get_splitpoint_time(status->splitpoint_to_move, ui);
2639  }
2640 
2641  return TRUE;
2642  }
2643 
2644  //right click
2645  if (event->button == 3)
2646  {
2647  status->button_x2 = event->x;
2648  status->button_y2 = event->y;
2649  status->button2_pressed = TRUE;
2650  infos->zoom_coeff_old = infos->zoom_coeff;
2651 
2652  if ((status->button_y2 > gui->progress_ylimit + gui->margin) &&
2653  (status->button_y2 < gui->progress_ylimit + gui->margin + gui->real_move_split_length))
2654  {
2655  player_quick_preview(get_splitpoint_clicked(status->button_y2, 3, 2, ui), ui);
2656  }
2657  else
2658  {
2659  //to remove a splitpoint
2660  if ((status->button_y2 > gui->margin) &&
2661  (status->button_y2 < gui->margin + gui->real_erase_split_length))
2662  {
2663  gint splitpoint_to_erase = get_splitpoint_clicked(status->button_y2, 3, 1, ui);
2664  if (splitpoint_to_erase != -1)
2665  {
2666  status->remove_splitpoints = TRUE;
2667  remove_splitpoint(splitpoint_to_erase, TRUE, ui);
2668  }
2669 
2670  refresh_drawing_area(gui);
2671  }
2672  }
2673  }
2674 
2675  return TRUE;
2676 }
2677 
2679 static gboolean da_unpress_event(GtkWidget *da, GdkEventButton *event, ui_state *ui)
2680 {
2681  gui_status *status = ui->status;
2682 
2683  if (!status->playing || !status->timer_active)
2684  {
2685  goto end;
2686  }
2687 
2688  if (event->button == 1)
2689  {
2690  status->button1_pressed = FALSE;
2691 
2692  //if moving the current _position_
2693  if (!status->move_splitpoints && !status->remove_splitpoints &&
2694  !status->select_splitpoints && !status->check_splitpoint)
2695  {
2696  remove_status_message(ui->gui);
2697  player_seek((gint)(status->move_time * 10), ui);
2698  change_progress_bar(ui);
2699 
2700  //if more than 2 splitpoints & outside the split preview, cancel split preview
2701  if (get_quick_preview_end_splitpoint_safe(ui) == -1)
2702  {
2703  if (status->move_time < get_splitpoint_time(status->preview_start_splitpoint, ui))
2704  {
2706  }
2707  }
2708  else
2709  {
2710  if ((status->move_time < get_splitpoint_time(status->preview_start_splitpoint, ui)) ||
2711  (status->move_time > get_splitpoint_time(get_quick_preview_end_splitpoint_safe(ui),ui)))
2712  {
2714  }
2715  else
2716  {
2717  //if don't have a preview with the last splitpoint
2718  if (get_quick_preview_end_splitpoint_safe(ui) != -1)
2719  {
2720  if (player_is_paused(ui))
2721  {
2722  player_pause(ui);
2723  }
2724  status->quick_preview = TRUE;
2725  }
2726  }
2727  }
2728  }
2729  else if (status->move_splitpoints)
2730  {
2731  update_splitpoint_from_time(status->splitpoint_to_move, status->move_time, ui);
2732  status->splitpoint_to_move = -1;
2733  }
2734 
2735  status->move_splitpoints = FALSE;
2736  status->select_splitpoints = FALSE;
2737  status->check_splitpoint = FALSE;
2738  }
2739  else if (event->button == 3)
2740  {
2741  status->button2_pressed = FALSE;
2742  status->remove_splitpoints = FALSE;
2743  }
2744 
2745 end:
2746  refresh_drawing_area(ui->gui);
2747  return TRUE;
2748 }
2749 
2751 static gboolean da_notify_event(GtkWidget *da, GdkEventMotion *event, ui_state *ui)
2752 {
2753  gui_status *status = ui->status;
2754  ui_infos *infos = ui->infos;
2755 
2756  if ((status->playing && status->timer_active) &&
2757  (status->button1_pressed || status->button2_pressed))
2758  {
2759  gint x, y;
2760  GdkModifierType state;
2761  wh_get_pointer(event, &x, &y, &state);
2762 
2763  gint width = 0;
2764  wh_get_widget_size(ui->gui->drawing_area, &width, NULL);
2765  gfloat width_drawing_area = (gfloat) width;
2766 
2767  if (!state)
2768  {
2769  return TRUE;
2770  }
2771 
2772  if (status->button1_pressed)
2773  {
2774  if (status->move_splitpoints)
2775  {
2776  gdouble splitpoint_time = get_splitpoint_time(status->splitpoint_to_move, ui);
2777  status->move_time = splitpoint_time +
2778  pixels_to_time(width_drawing_area, (x - status->button_x), ui);
2779  }
2780  else
2781  {
2782  if (status->remove_splitpoints || status->select_splitpoints || status->check_splitpoint)
2783  {
2784  status->move_time = infos->current_time;
2785  }
2786  else
2787  {
2788  status->move_time =
2789  infos->current_time + pixels_to_time(width_drawing_area, (x - status->button_x), ui);
2790  }
2791  }
2792 
2793  if (status->move_time < 0)
2794  {
2795  status->move_time = 0;
2796  }
2797  if (status->move_time > infos->total_time)
2798  {
2799  status->move_time = infos->total_time;
2800  }
2801 
2802  refresh_drawing_area(ui->gui);
2803  }
2804  else
2805  {
2806  if (status->button2_pressed)
2807  {
2808  gint diff = -((event->x - status->button_x2) * 1);
2809  if (diff < (-width_drawing_area + 1))
2810  {
2811  diff = -width_drawing_area + 1;
2812  }
2813  if (diff > (width_drawing_area - 1))
2814  {
2815  diff = width_drawing_area - 1;
2816  }
2817 
2818  infos->zoom_coeff = diff / (width_drawing_area);
2819 
2820  if (infos->zoom_coeff < 0)
2821  {
2822  infos->zoom_coeff = 1 / (infos->zoom_coeff + 1);
2823  }
2824  else
2825  {
2826  infos->zoom_coeff = 1 - infos->zoom_coeff;
2827  }
2828 
2829  infos->zoom_coeff = infos->zoom_coeff_old * infos->zoom_coeff;
2830 
2831  adjust_zoom_coeff(infos);
2832 
2833  refresh_drawing_area(ui->gui);
2834  }
2835  }
2836  }
2837 
2838  return TRUE;
2839 }
2840 
2841 void adjust_zoom_coeff(ui_infos *infos)
2842 {
2843  if (infos->zoom_coeff < 0.2)
2844  {
2845  infos->zoom_coeff = 0.2;
2846  }
2847  if (infos->zoom_coeff > 10 * infos->total_time / 6000)
2848  {
2849  infos->zoom_coeff = 10 * infos->total_time / 6000;
2850  }
2851 }
2852 
2853 static void drawing_area_expander_event(GObject *object, GParamSpec *param_spec, ui_state *ui)
2854 {
2855  if (object == NULL)
2856  {
2857  return;
2858  }
2859 
2860  GtkExpander *expander = GTK_EXPANDER(object);
2861  if (gtk_expander_get_expanded(expander))
2862  {
2863  gtk_widget_show(ui->gui->silence_wave_check_button);
2864  return;
2865  }
2866 
2867  gtk_widget_hide(ui->gui->silence_wave_check_button);
2868 }
2869 
2871 static GtkWidget *create_drawing_area(ui_state *ui)
2872 {
2873  GtkWidget *frame = gtk_frame_new(NULL);
2874 
2875  GdkColor color;
2876  color.red = 65000; color.green = 0; color.blue = 0;
2877  gtk_widget_modify_bg(frame, GTK_STATE_NORMAL, &color);
2878 
2879  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
2880 
2881  GtkWidget *drawing_area = gtk_drawing_area_new();
2882  dnd_add_drag_data_received_to_widget(drawing_area,
2883  DND_SINGLE_MODE_AUDIO_FILE_AND_DATA_FILES, ui);
2884 
2885  ui->gui->drawing_area = drawing_area;
2886 
2887  gtk_widget_set_size_request(drawing_area, DRAWING_AREA_WIDTH, DRAWING_AREA_HEIGHT);
2888 
2889 #if GTK_MAJOR_VERSION <= 2
2890  g_signal_connect(drawing_area, "expose_event", G_CALLBACK(da_draw_event), ui);
2891 #else
2892  g_signal_connect(drawing_area, "draw", G_CALLBACK(da_draw_event), ui);
2893 #endif
2894 
2895  g_signal_connect(drawing_area, "button_press_event", G_CALLBACK(da_press_event), ui);
2896  g_signal_connect(drawing_area, "button_release_event", G_CALLBACK(da_unpress_event), ui);
2897  g_signal_connect(drawing_area, "motion_notify_event", G_CALLBACK(da_notify_event), ui);
2898 
2899  gtk_widget_set_events(drawing_area, gtk_widget_get_events(drawing_area)
2900  | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK
2901  | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK
2902  | GDK_POINTER_MOTION_HINT_MASK);
2903 
2904  gtk_container_add(GTK_CONTAINER(frame), drawing_area);
2905 
2906  GtkWidget *drawing_area_expander =
2907  gtk_expander_new_with_mnemonic(_("Splitpoints and amplitude wave v_iew"));
2908  ui->gui->drawing_area_expander = drawing_area_expander;
2909  gtk_expander_set_expanded(GTK_EXPANDER(drawing_area_expander), TRUE);
2910  g_signal_connect(drawing_area_expander, "notify::expanded",
2911  G_CALLBACK(drawing_area_expander_event), ui);
2912  gtk_container_add(GTK_CONTAINER(drawing_area_expander), frame);
2913 
2914  return drawing_area_expander;
2915 }
2916 
2919 {
2920  GtkWidget *main_hbox = wh_hbox_new();
2921 
2922  GtkWidget *vbox = wh_vbox_new();
2923  gtk_box_pack_start(GTK_BOX(main_hbox), vbox, TRUE, TRUE, 0);
2924 
2925  //filename player hbox
2926  GtkWidget *hbox = create_filename_player_hbox(ui->gui);
2927  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2928 
2929  //the song informations
2930  hbox = create_song_informations_hbox(ui->gui);
2931  gtk_container_set_border_width(GTK_CONTAINER (hbox), 0);
2932  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 3);
2933 
2934  //audio progress bar
2935  hbox = create_song_bar_hbox(ui);
2936  gtk_container_set_border_width(GTK_CONTAINER(hbox), 0);
2937  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2938 
2939  //drawing area
2940  GtkWidget *drawing_area = create_drawing_area(ui);
2941  gtk_container_set_border_width(GTK_CONTAINER(drawing_area), 0);
2942  gtk_box_pack_start(GTK_BOX(vbox), drawing_area, FALSE, FALSE, 0);
2943 
2944  //player buttons
2945  hbox = create_player_buttons_hbox(ui);
2946  gtk_container_set_border_width(GTK_CONTAINER(hbox), 0);
2947  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2948 
2949  return main_hbox;
2950 }
2951 
2953 void add_playlist_file(const gchar *name, ui_state *ui)
2954 {
2955  if (!file_exists(name))
2956  {
2957  return;
2958  }
2959 
2960  gboolean name_already_exists_in_playlist = FALSE;
2961 
2962  GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->playlist_tree);
2963 
2964  gchar *filename = NULL;
2965 
2966  GtkTreeIter iter;
2967 
2968  gint i = 0;
2969  while (i < ui->infos->playlist_tree_number)
2970  {
2971  GtkTreePath *path = gtk_tree_path_new_from_indices(i ,-1);
2972  gtk_tree_model_get_iter(model, &iter, path);
2973  gtk_tree_model_get(model, &iter, COL_FILENAME, &filename, -1);
2974 
2975  if (strcmp(filename, name) == 0)
2976  {
2977  name_already_exists_in_playlist = TRUE;
2978  break;
2979  }
2980 
2981  g_free(filename);
2982  i++;
2983  }
2984 
2985  if (! name_already_exists_in_playlist)
2986  {
2987  gtk_widget_set_sensitive(ui->gui->playlist_remove_all_files_button,TRUE);
2988  gtk_list_store_append(GTK_LIST_STORE(model), &iter);
2989 
2990  //sets text in the minute, second and milisecond column
2991  gtk_list_store_set (GTK_LIST_STORE(model),
2992  &iter,
2993  COL_NAME, get_real_name_from_filename(name),
2994  COL_FILENAME, name,
2995  -1);
2996  ui->infos->playlist_tree_number++;
2997  }
2998 }
2999 
3000 static GtkTreeModel *create_playlist_model()
3002 {
3003  GtkListStore * model = gtk_list_store_new(PLAYLIST_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
3004  return GTK_TREE_MODEL(model);
3005 }
3006 
3008 static GtkTreeView *create_playlist_tree()
3009 {
3010  GtkTreeModel *model = create_playlist_model();
3011  GtkTreeView *playlist_tree = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
3012  gtk_tree_view_set_headers_visible(playlist_tree, FALSE);
3013  return playlist_tree;
3014 }
3015 
3017 void create_playlist_columns(GtkTreeView *playlist_tree)
3018 {
3019  GtkCellRendererText *renderer = GTK_CELL_RENDERER_TEXT(gtk_cell_renderer_text_new());
3020  g_object_set_data(G_OBJECT(renderer), "col", GINT_TO_POINTER(COL_NAME));
3021 
3022  GtkTreeViewColumn *name_column = gtk_tree_view_column_new_with_attributes
3023  (_("History"), GTK_CELL_RENDERER(renderer), "text", COL_NAME, NULL);
3024  gtk_tree_view_insert_column(playlist_tree, GTK_TREE_VIEW_COLUMN(name_column), COL_NAME);
3025 
3026  gtk_tree_view_column_set_alignment(GTK_TREE_VIEW_COLUMN(name_column), 0.5);
3027  gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(name_column), GTK_TREE_VIEW_COLUMN_AUTOSIZE);
3028 }
3029 
3031 static void playlist_selection_changed(GtkTreeSelection *selec, ui_state *ui)
3032 {
3033  GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->playlist_tree);
3034  GtkTreeSelection *selection = gtk_tree_view_get_selection(ui->gui->playlist_tree);
3035  GList *selected_list = gtk_tree_selection_get_selected_rows(selection, &model);
3036  if (g_list_length(selected_list) > 0)
3037  {
3038  gtk_widget_set_sensitive(ui->gui->playlist_remove_file_button, TRUE);
3039  }
3040  else
3041  {
3042  gtk_widget_set_sensitive(ui->gui->playlist_remove_file_button, FALSE);
3043  }
3044 }
3045 
3047 static void playlist_remove_file_button_event(GtkWidget *widget, ui_state *ui)
3048 {
3049  GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->playlist_tree);
3050  GtkTreeSelection *selection = gtk_tree_view_get_selection(ui->gui->playlist_tree);
3051  GList *selected_list = gtk_tree_selection_get_selected_rows(selection, &model);
3052 
3053  gchar *filename = NULL;
3054 
3055  while (g_list_length(selected_list) > 0)
3056  {
3057  GList *current_element = g_list_last(selected_list);
3058  GtkTreePath *path = current_element->data;
3059 
3060  GtkTreeIter iter;
3061  gtk_tree_model_get_iter(model, &iter, path);
3062  gtk_tree_model_get(model, &iter,
3063  COL_FILENAME, &filename, -1);
3064 
3065  //remove the path from the selected list
3066  gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
3067  selected_list = g_list_remove(selected_list, path);
3068  //remove 1 to the row number of the table
3069  ui->infos->playlist_tree_number--;
3070 
3071  gtk_tree_path_free(path);
3072  g_free(filename);
3073  }
3074 
3075  if (ui->infos->playlist_tree_number == 0)
3076  {
3077  gtk_widget_set_sensitive(ui->gui->playlist_remove_all_files_button, FALSE);
3078  }
3079 
3080  gtk_widget_set_sensitive(ui->gui->playlist_remove_file_button,FALSE);
3081 
3082  g_list_foreach(selected_list, (GFunc)gtk_tree_path_free, NULL);
3083  g_list_free(selected_list);
3084 }
3085 
3087 static void playlist_remove_all_files_button_event(GtkWidget *widget, ui_state *ui)
3088 {
3089  GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->playlist_tree);
3090 
3091  gchar *filename = NULL;
3092  while (ui->infos->playlist_tree_number > 0)
3093  {
3094  GtkTreeIter iter;
3095  gtk_tree_model_get_iter_first(model, &iter);
3096  gtk_tree_model_get(model, &iter,
3097  COL_FILENAME, &filename, -1);
3098  gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
3099  ui->infos->playlist_tree_number--;
3100  g_free(filename);
3101  }
3102 
3103  gtk_widget_set_sensitive(ui->gui->playlist_remove_all_files_button, FALSE);
3104  gtk_widget_set_sensitive(ui->gui->playlist_remove_file_button, FALSE);
3105 }
3106 
3108 static GtkWidget *create_delete_buttons_hbox(ui_state *ui)
3109 {
3110  GtkWidget *hbox = wh_hbox_new();
3111 
3112  GtkWidget *playlist_remove_file_button =
3113  wh_create_cool_button(GTK_STOCK_REMOVE, _("_Erase selected entries"), FALSE);
3114  ui->gui->playlist_remove_file_button = playlist_remove_file_button;
3115  gtk_box_pack_start(GTK_BOX(hbox), playlist_remove_file_button, FALSE, FALSE, 5);
3116  gtk_widget_set_sensitive(playlist_remove_file_button,FALSE);
3117  g_signal_connect(G_OBJECT(playlist_remove_file_button), "clicked",
3118  G_CALLBACK(playlist_remove_file_button_event), ui);
3119 
3120  GtkWidget *playlist_remove_all_files_button =
3121  wh_create_cool_button(GTK_STOCK_CLEAR, _("E_rase all history"),FALSE);
3122  ui->gui->playlist_remove_all_files_button = playlist_remove_all_files_button;
3123  gtk_box_pack_start(GTK_BOX(hbox), playlist_remove_all_files_button, FALSE, FALSE, 5);
3124  gtk_widget_set_sensitive(playlist_remove_all_files_button,FALSE);
3125  g_signal_connect(G_OBJECT(playlist_remove_all_files_button), "clicked",
3126  G_CALLBACK(playlist_remove_all_files_button_event), ui);
3127 
3128  return hbox;
3129 }
3130 
3133 {
3134  GtkWidget *vbox = wh_vbox_new();
3135 
3136  //scrolled window and the tree
3137  //create the tree and add it to the scrolled window
3138  GtkTreeView *playlist_tree = create_playlist_tree();
3139  dnd_add_drag_data_received_to_widget(GTK_WIDGET(playlist_tree), DND_SINGLE_MODE_AUDIO_FILE, ui);
3140 
3141  ui->gui->playlist_tree = playlist_tree;
3142  GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
3143  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_NONE);
3144  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
3145  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3146  gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);
3147 
3148  create_playlist_columns(playlist_tree);
3149  gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(playlist_tree));
3150  g_signal_connect(G_OBJECT(playlist_tree), "row-activated",
3151  G_CALLBACK(split_tree_row_activated), ui);
3152 
3153  //selection for the tree
3154  GtkTreeSelection *playlist_tree_selection = gtk_tree_view_get_selection(playlist_tree);
3155  g_signal_connect(G_OBJECT(playlist_tree_selection), "changed",
3156  G_CALLBACK(playlist_selection_changed), ui);
3157  gtk_tree_selection_set_mode(GTK_TREE_SELECTION(playlist_tree_selection), GTK_SELECTION_MULTIPLE);
3158 
3159  //horizontal box with delete buttons
3160  GtkWidget *delete_buttons_hbox = create_delete_buttons_hbox(ui);
3161  gtk_box_pack_start(GTK_BOX(vbox), delete_buttons_hbox, FALSE, FALSE, 2);
3162 
3163  GtkWidget *history_expander = gtk_expander_new_with_mnemonic(_("Files h_istory"));
3164  gtk_expander_set_expanded(GTK_EXPANDER(history_expander), FALSE);
3165  gtk_container_add(GTK_CONTAINER(history_expander), vbox);
3166 
3167  GtkWidget *main_hbox = wh_hbox_new();
3168  gtk_box_pack_start(GTK_BOX(main_hbox), history_expander, TRUE, TRUE, 4);
3169 
3170  return main_hbox;
3171 }
3172 
3173 static void action_set_sensitivity(gchar *name, gboolean sensitivity, gui_state *gui)
3174 {
3175  GtkAction *action = gtk_action_group_get_action(gui->action_group, name);
3176  gtk_action_set_sensitive(action, sensitivity);
3177 }
3178 
3179 void player_key_actions_set_sensitivity(gboolean sensitivity, gui_state *gui)
3180 {
3181  action_set_sensitivity("Player_pause", sensitivity, gui);
3182  action_set_sensitivity("Player_forward", sensitivity, gui);
3183  action_set_sensitivity("Player_backward", sensitivity, gui);
3184  action_set_sensitivity("Player_small_forward", sensitivity, gui);
3185  action_set_sensitivity("Player_small_backward", sensitivity, gui);
3186  action_set_sensitivity("Player_big_forward", sensitivity, gui);
3187  action_set_sensitivity("Player_big_backward", sensitivity, gui);
3188  action_set_sensitivity("Player_next_splitpoint", sensitivity, gui);
3189  action_set_sensitivity("Player_previous_splitpoint", sensitivity, gui);
3190  action_set_sensitivity("Add_splitpoint", sensitivity, gui);
3191  action_set_sensitivity("Delete_closest_splitpoint", sensitivity, gui);
3192  action_set_sensitivity("Zoom_in", sensitivity, gui);
3193  action_set_sensitivity("Zoom_out", sensitivity, gui);
3194 }
3195 
3200 static gint mytimer(ui_state *ui)
3201 {
3202 #ifdef __WIN32__
3203  if (get_process_in_progress_safe(ui))
3204  {
3205  return TRUE;
3206  }
3207 #endif
3208 
3209  set_process_in_progress_safe(TRUE, ui);
3210 
3211  ui_infos *infos = ui->infos;
3212  gui_state *gui = ui->gui;
3213  gui_status *status = ui->status;
3214 
3215  //TODO: file from file chooser can be NULL and != from the real filename of mp3splt-gtk.
3216  //but this does not work: the user can no longer select a folder if we do this
3217  /*if (gui->open_file_chooser_button != NULL)
3218  {
3219  gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(gui->open_file_chooser_button));
3220  if (filename == NULL)
3221  {
3222  gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(gui->open_file_chooser_button),
3223  get_input_filename(ui->gui));
3224  }
3225  }*/
3226 
3227  if (!player_is_running(ui))
3228  {
3229  gtk_widget_set_sensitive(gui->silence_wave_check_button, FALSE);
3230 
3231  clear_data_player(gui);
3232  status->playing = FALSE;
3233  disconnect_button_event(gui->disconnect_button, ui);
3234 
3235  set_process_in_progress_safe(FALSE, ui);
3236  return FALSE;
3237  }
3238 
3239  gtk_widget_set_sensitive(gui->silence_wave_check_button, TRUE);
3240 
3241  if (status->playing)
3242  {
3243  if (player_get_playlist_number(ui) > -1)
3244  {
3245  if (player_is_playing(ui))
3246  {
3247  print_all_song_infos(ui);
3248  print_song_time_elapsed(ui);
3249  gtk_widget_set_sensitive(GTK_WIDGET(gui->progress_bar), TRUE);
3250  }
3251 
3252  check_stream(ui);
3253 
3254  //if we have a stream, we must not change the progress bar
3255  if (!status->stream)
3256  {
3257  change_progress_bar(ui);
3258  }
3259 
3260  //part of quick preview
3261  if (status->preview_start_splitpoint != -1)
3262  {
3263  //if we have a splitpoint after the current
3264  //previewed one, update quick_preview_end
3265  if (status->preview_start_splitpoint + 1 < infos->splitnumber)
3266  {
3267  set_quick_preview_end_splitpoint_safe(status->preview_start_splitpoint + 1, ui);
3268  }
3269  else
3270  {
3271  if (status->preview_start_splitpoint + 1 == infos->splitnumber)
3272  {
3273  set_quick_preview_end_splitpoint_safe(-1, ui);
3274  }
3275  }
3276  }
3277 
3278  //if we have a preview, stop if needed
3279  if (status->quick_preview)
3280  {
3281  gint stop_splitpoint = get_splitpoint_time(get_quick_preview_end_splitpoint_safe(ui), ui);
3282 
3283  if ((stop_splitpoint < (gint)infos->current_time)
3284  && (get_quick_preview_end_splitpoint_safe(ui) != -1))
3285  {
3286  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui->pause_button), TRUE);
3287  cancel_quick_preview(status);
3288  put_status_message(_(" quick preview finished, song paused"), ui);
3289  }
3290  }
3291 
3292  gtk_widget_set_sensitive(GTK_WIDGET(gui->volume_button), TRUE);
3293  }
3294  else
3295  {
3296  status->playing = FALSE;
3297  reset_label_time(gui);
3298  }
3299 
3300  if (player_is_paused(ui))
3301  {
3302  status->only_press_pause = TRUE;
3303  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui->pause_button), TRUE);
3304  status->only_press_pause = FALSE;
3305  }
3306  else
3307  {
3308  status->only_press_pause = TRUE;
3309  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui->pause_button), FALSE);
3310  status->only_press_pause = FALSE;
3311  }
3312  }
3313  else
3314  {
3315  if ((infos->player_minutes != 0) || (infos->player_seconds != 0))
3316  {
3317  infos->player_minutes = 0;
3318  infos->player_seconds = 0;
3319  }
3320 
3321  print_player_filename(ui);
3322  reset_song_infos(gui);
3323  reset_label_time(gui);
3324  reset_inactive_progress_bar(gui);
3325  gtk_widget_set_sensitive(gui->player_add_button, FALSE);
3326  }
3327 
3328  //if connected, almost always change volume bar
3329  if ((ui->status->change_volume)&& (!ui->status->on_the_volume_button))
3330  {
3331  change_volume_button(ui);
3332  }
3333 
3334  status->playing = player_is_playing(ui);
3335  if (status->playing)
3336  {
3337  gtk_widget_set_sensitive(gui->player_add_button, TRUE);
3338  gtk_widget_set_sensitive(gui->stop_button, TRUE);
3339  wh_set_image_on_button(GTK_BUTTON(gui->stop_button), g_object_ref(gui->StopButton_active));
3340 
3341  gtk_widget_set_sensitive(gui->pause_button, TRUE);
3342  wh_set_image_on_button(GTK_BUTTON(gui->pause_button), g_object_ref(gui->PauseButton_active));
3343 
3344  player_key_actions_set_sensitivity(TRUE, gui);
3345  }
3346  else
3347  {
3348  gtk_widget_set_sensitive(gui->stop_button, FALSE);
3349  wh_set_image_on_button(GTK_BUTTON(gui->stop_button), g_object_ref(gui->StopButton_inactive));
3350 
3351  gtk_widget_set_sensitive(gui->pause_button, FALSE);
3352  wh_set_image_on_button(GTK_BUTTON(gui->pause_button), g_object_ref(gui->PauseButton_inactive));
3353 
3354  player_key_actions_set_sensitivity(FALSE, gui);
3355  }
3356 
3357  set_process_in_progress_safe(FALSE, ui);
3358 
3359  return TRUE;
3360 }
3361 
3362 //event for the file chooser ok button
3363 void file_chooser_ok_event(gchar *fname, ui_state *ui)
3364 {
3365  change_current_filename(fname, ui);
3366  gtk_widget_set_sensitive(ui->gui->play_button, TRUE);
3367  wh_set_image_on_button(GTK_BUTTON(ui->gui->play_button), g_object_ref(ui->gui->PlayButton_active));
3368 
3369  ui->status->file_browsed = TRUE;
3370 
3371  if (ui->status->timer_active)
3372  {
3373  GList *song_list = NULL;
3374  song_list = g_list_append(song_list, fname);
3375 
3376  if (!player_is_running(ui))
3377  {
3378  player_start(ui);
3379  }
3380  else if (ui->status->playing)
3381  {
3382  player_stop(ui);
3383  }
3384 
3385  player_add_files_and_select(song_list, ui);
3386 
3387  if (ui->status->playing && !player_is_paused(ui))
3388  {
3389  player_play(ui);
3390  }
3391  }
3392 }
3393