1 /*
2  *	Copyright (C) 2004-2005 Vadim Berezniker
3  *	http://www.kryptolus.com
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with GNU Make; see the file COPYING.  If not, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21 
22 
23 #include "stdafx.h"
24 
25 #include "common.h"
26 
27 #include "pavl.h"
28 #include "kry_marker.h"
29 #include "kry_region.h"
30 #include "kry_region_fixed_list.h"
31 #include "kry_waveform.h"
32 #include "kry_waveform_group_item.h"
33 #include "sound.h"
34 
35 static void kry_waveform_class_init (KryWaveformClass *klass);
36 static void kry_waveform_init (KryWaveform *waveform);
37 static void kry_waveform_destroy (GtkObject *object);
38 static void kry_waveform_realize (GtkWidget *widget);
39 static void kry_waveform_find_first_region(KryWaveform *waveform, gboolean backward);
40 
41 static void kry_waveform_size_request (GtkWidget      *widget, GtkRequisition *requisition);
42 void kry_waveform_size_allocate (GtkWidget     *widget, GtkAllocation *allocation);
43 static gboolean kry_waveform_button_press( GtkWidget      *widget, GdkEventButton *event );
44 static gboolean kry_waveform_button_release( GtkWidget      *widget, GdkEventButton *event );
45 static gboolean kry_waveform_motion_notify( GtkWidget      *widget, GdkEventMotion *event );
46 static void kry_waveform_adjustment_value_changed (GtkAdjustment *adjustment, gpointer       data);
47 void kry_waveform_set_data(KryWaveform *waveform, struct sound_info *sound_info);
48 static gboolean kry_waveform_key_press( GtkWidget      *widget, GdkEventKey *event );
49 static void kry_waveform_redraw(KryWaveform *waveform);
50 static GtkWidgetClass *parent_class = NULL;
51 static double kry_waveform_get_zoom_internal(KryWaveform *waveform);
52 static void kry_waveform_update_zoom(KryWaveform *waveform);
53 
54 struct waveform_state
55 {
56   int width;
57   int height;
58 };
59 
60 
61 enum
62 {
63   ZOOM_CHANGED_SIGNAL,
64   SCALE_CHANGED_SIGNAL,
65   MIN_ZOOM_CHANGED_SIGNAL,
66   LAST_SIGNAL
67 };
68 
69 static guint kry_waveform_signals[LAST_SIGNAL] = { 0 };
70 
kry_waveform_get_type()71 GtkType kry_waveform_get_type ()
72 {
73   static GtkType waveform_type = 0;
74 
75   if (!waveform_type)
76   {
77     static const GtkTypeInfo waveform_info =
78     {
79       "KryWaveform",
80       sizeof (KryWaveform),
81       sizeof (KryWaveformClass),
82       (GtkClassInitFunc) kry_waveform_class_init,
83       (GtkObjectInitFunc) kry_waveform_init,
84       /* reserved_1 */ NULL,
85       /* reserved_1 */ NULL,
86       (GtkClassInitFunc) NULL
87     };
88 
89     waveform_type = gtk_type_unique (GTK_TYPE_WIDGET, &waveform_info);
90   }
91 
92   return waveform_type;
93 }
94 
kry_waveform_class_init(KryWaveformClass * klass)95 static void kry_waveform_class_init (KryWaveformClass *klass)
96 {
97   GtkObjectClass *object_class;
98   GtkWidgetClass *widget_class;
99 
100   object_class = (GtkObjectClass*) klass;
101   widget_class = (GtkWidgetClass*) klass;
102 
103   parent_class = GTK_WIDGET_CLASS(gtk_type_class (gtk_widget_get_type ()));
104 
105   object_class->destroy = kry_waveform_destroy;
106 
107   widget_class->realize = kry_waveform_realize;
108   widget_class->expose_event = kry_waveform_expose;
109   widget_class->size_request = kry_waveform_size_request;
110   widget_class->size_allocate = kry_waveform_size_allocate;
111   widget_class->button_press_event = kry_waveform_button_press;
112   widget_class->button_release_event = kry_waveform_button_release;
113   widget_class->motion_notify_event = kry_waveform_motion_notify;
114   widget_class->key_press_event = kry_waveform_key_press;
115 
116   kry_waveform_signals[ZOOM_CHANGED_SIGNAL] =
117     g_signal_new ("zoom_changed",
118 		  G_OBJECT_CLASS_TYPE (klass),
119 		  (GSignalFlags) (G_SIGNAL_RUN_FIRST),
120 		  G_STRUCT_OFFSET (KryWaveformClass, zoom_changed),
121 		  NULL, NULL,
122       g_cclosure_marshal_VOID__DOUBLE,
123       G_TYPE_NONE, 1, G_TYPE_DOUBLE);
124 
125   kry_waveform_signals[SCALE_CHANGED_SIGNAL] =
126     g_signal_new ("scale_changed",
127 		  G_OBJECT_CLASS_TYPE (klass),
128 		  (GSignalFlags) (G_SIGNAL_RUN_FIRST),
129 		  G_STRUCT_OFFSET (KryWaveformClass, scale_changed),
130 		  NULL, NULL,
131       g_cclosure_marshal_VOID__INT,
132       G_TYPE_NONE, 1, G_TYPE_INT);
133 
134   kry_waveform_signals[MIN_ZOOM_CHANGED_SIGNAL] =
135     g_signal_new ("min_zoom_changed",
136 		  G_OBJECT_CLASS_TYPE (klass),
137 		  (GSignalFlags) (G_SIGNAL_RUN_FIRST),
138 		  G_STRUCT_OFFSET (KryWaveformClass, min_zoom_changed),
139 		  NULL, NULL,
140       g_cclosure_marshal_VOID__DOUBLE,
141       G_TYPE_NONE, 1, G_TYPE_DOUBLE);
142 }
143 
144 static void
kry_waveform_init(KryWaveform * waveform)145 kry_waveform_init (KryWaveform *waveform)
146 {
147   waveform->button_press = FALSE;
148   waveform->data_per_pixel = 1;
149   waveform->scale = 1;
150   waveform->show_scrub_bar = TRUE;
151   waveform->show_time_bar = TRUE;
152   waveform->show_time_markers = TRUE;
153   waveform->show_keyframe = TRUE;
154   waveform->scrub_bar_height = 15;
155   waveform->scrub_bar_height_real = 15;
156   waveform->drag_selection_enabled = TRUE;
157   waveform->zoom = 3.0;
158   waveform->marker_width = 2;
159   waveform->corner_width = 8;
160   waveform->data_thread_mutex = g_mutex_new();
161   waveform->data_thread_mutex_global = g_mutex_new();
162   waveform->region_fixed_list = NULL;
163 }
164 
kry_waveform_disable_draw(KryWaveform * widget)165 void kry_waveform_disable_draw(KryWaveform *widget)
166 {
167   KryWaveform *waveform;
168 
169   g_return_if_fail (widget != NULL);
170   g_return_if_fail (KRY_IS_WAVEFORM (widget));
171 
172   waveform = KRY_WAVEFORM(widget);
173 
174   waveform->draw_disabled = TRUE;
175 }
176 
kry_waveform_enable_draw(KryWaveform * widget)177 void kry_waveform_enable_draw(KryWaveform *widget)
178 {
179   KryWaveform *waveform;
180 
181   g_return_if_fail (widget != NULL);
182   g_return_if_fail (KRY_IS_WAVEFORM (widget));
183 
184   waveform = KRY_WAVEFORM(widget);
185 
186   waveform->draw_disabled = FALSE;
187 
188   kry_waveform_redraw(waveform);
189 }
190 
kry_waveform_marker_draw_erase_real(KryWaveform * waveform,int pos_rel_pixel,gboolean erase)191 void kry_waveform_marker_draw_erase_real(KryWaveform *waveform, int pos_rel_pixel, gboolean erase)
192 {
193 
194   GList *list = NULL;
195   struct KryWaveformMarkerInfo *info = NULL;
196   int width = waveform->marker_width;
197   if(!erase)
198   {
199     info = kry_new(struct KryWaveformMarkerInfo, 1);
200     info->marker = NULL;
201     info->pos_rel_pixel = pos_rel_pixel;
202     list = g_list_append(NULL, info);
203     waveform->markers = g_list_concat(waveform->markers, list);
204   }
205 
206   kry_waveform_backbuffer_draw_final(GTK_WIDGET(waveform), pos_rel_pixel, width, TRUE, FALSE);
207 
208   if(!erase)
209   {
210     waveform->markers = g_list_delete_link(waveform->markers, list);
211     kry_free(info);
212   }
213 }
214 
215 /*void kry_waveform_marker_draw_erase(GtkWidget *widget, int mili, int mili_prev)
216 {
217   KryWaveform *waveform;
218 
219   g_return_if_fail (widget != NULL);
220   g_return_if_fail (KRY_IS_WAVEFORM (widget));
221 
222   waveform = KRY_WAVEFORM(widget);
223 
224   int pos_rel_pixel = kry_waveform_rel_pixel_from_mili(waveform, mili);
225   int pos_rel_pixel_prev = kry_waveform_rel_pixel_from_mili(waveform, mili_prev);
226 
227   if(mili_prev != -1)
228     kry_waveform_marker_draw_erase_real(waveform, pos_rel_pixel_prev, TRUE);
229 
230   if(mili != -1)
231     kry_waveform_marker_draw_erase_real(waveform, pos_rel_pixel, FALSE);
232 
233   if(mili == -1)
234     kry_waveform_update_front_buffer(waveform, pos_rel_pixel_prev, waveform->marker_width);
235   else if(mili_prev == -1)
236     kry_waveform_update_front_buffer(waveform, pos_rel_pixel, waveform->marker_width);
237   else
238     kry_waveform_update_front_buffer(waveform, pos_rel_pixel_prev, pos_rel_pixel - pos_rel_pixel_prev + waveform->marker_width);
239 }
240 
241 void kry_waveform_marker_erase(GtkWidget *widget, int mili)
242 {
243   kry_waveform_marker_draw_erase(widget, mili, TRUE);
244 }*/
245 
kry_waveform_redraw_partial(KryWaveform * waveform,int start,int width,gboolean redraw_time_bar,gboolean do_draw)246 static void kry_waveform_redraw_partial(KryWaveform *waveform, int start, int width, gboolean redraw_time_bar, gboolean do_draw)
247 {
248   if(!GTK_WIDGET_REALIZED(waveform))
249     return;
250 
251   kry_waveform_backbuffer_draw_final(GTK_WIDGET(waveform), start, width, TRUE, redraw_time_bar);
252 
253   if(do_draw)
254     kry_waveform_update_front_buffer(waveform, start, width);
255 }
256 
257 // redraws the entire wave. must be used only when necessary
kry_waveform_redraw(KryWaveform * waveform)258 static void kry_waveform_redraw(KryWaveform *waveform)
259 {
260   if(!GTK_WIDGET_REALIZED(waveform) || waveform->draw_disabled)
261     return;
262 
263   if(!waveform->data_pixel)
264     return;
265 
266   waveform->last_draw_rect.x = kry_waveform_abs_pixel_from_rel(waveform, 0);
267   waveform->last_draw_rect.width = GTK_WIDGET(waveform)->allocation.width;
268 
269   kry_waveform_backbuffer_draw_final(GTK_WIDGET(waveform), 0, GTK_WIDGET(waveform)->allocation.width, TRUE, TRUE);
270 
271   kry_waveform_update_front_buffer(waveform, 0, GTK_WIDGET(waveform)->allocation.width);
272 }
273 
kry_waveform_abs_pixel_from_mili(KryWaveform * waveform,long time)274 int kry_waveform_abs_pixel_from_mili(KryWaveform *waveform, long time)
275 {
276   return (int) ((((time / 1000.0) * waveform->data_info->vals_per_sec) / waveform->data_per_pixel));
277 }
278 
279 // gets a relative pixel position for the given time
280 // (relative to the left side of the waveform)
kry_waveform_rel_pixel_from_mili(KryWaveform * waveform,long time)281 int kry_waveform_rel_pixel_from_mili(KryWaveform *waveform, long time)
282 {
283   return (int) ((((time / 1000.0) * waveform->data_info->vals_per_sec) / waveform->data_per_pixel) - ((waveform->left - fmod(waveform->left, waveform->data_per_pixel)) / waveform->data_per_pixel));
284 }
285 
kry_waveform_abs_pixel_from_rel(KryWaveform * waveform,int pixel)286 int kry_waveform_abs_pixel_from_rel(KryWaveform *waveform, int pixel)
287 {
288   double abs = (pixel + waveform->left / waveform->data_per_pixel);
289   return (int) abs + 1;
290 }
291 
kry_waveform_mili_from_rel_pixel(KryWaveform * waveform,int pixel)292 int kry_waveform_mili_from_rel_pixel(KryWaveform *waveform, int pixel)
293 {
294   return (int) (((pixel + (waveform->left - fmod(waveform->left, waveform->data_per_pixel)) / waveform->data_per_pixel) * 1000.0 * waveform->data_per_pixel) / waveform->data_info->vals_per_sec);
295 }
296 
297 /*
298  * Invoked when a color in the color table used by the wave widget changes.
299  * This forces a redraw of the wave.
300  */
kry_waveform_color_changed(kryObject * obj,kryColor * color,KryWaveform * waveform)301 void kry_waveform_color_changed(kryObject *obj, kryColor *color, KryWaveform *waveform)
302 {
303   //kryColorTable *table = (kryColorTable *) obj;
304 #ifdef _WINDOWS
305   if(color->GetID() == WAVEFORM_COLOR_BACKGROUND)
306   {
307     DeleteObject(waveform->black_brush);
308     waveform->black_brush = CreateSolidBrush(RGB(color->GetRed(), color->GetGreen(), color->GetBlue()));
309   }
310 
311   HPEN pen = (HPEN) color->GetUserData();
312   LOGPEN pen_info;
313   GetObject(pen, sizeof(LOGPEN), &pen_info);
314 
315   if(   GetRValue(pen_info.lopnColor) != color->GetRed()
316     ||  GetGValue(pen_info.lopnColor) != color->GetGreen()
317     ||  GetBValue(pen_info.lopnColor) != color->GetBlue())
318   {
319     DeleteObject(color->GetUserData());
320     color->SetUserData(CreatePen(PS_SOLID, 1, RGB(color->GetRed(), color->GetGreen(), color->GetBlue())));
321   }
322 #else
323   GdkColor *gdkcolor = (GdkColor *) color->GetUserData();
324   gdkcolor->red = color->GetRed() * 255;
325   gdkcolor->green = color->GetGreen() * 255;
326   gdkcolor->blue = color->GetBlue() * 255;
327 #endif
328 
329   kry_waveform_redraw(waveform);
330 }
331 
kry_waveform_new(KryWaveformDataInfo * info,GtkAdjustment * adjustment,kryColorTable * color_table)332 GtkWidget *kry_waveform_new(KryWaveformDataInfo *info, GtkAdjustment *adjustment, kryColorTable *color_table)
333 {
334   KryWaveform *waveform;
335 
336   waveform = KRY_WAVEFORM(gtk_type_new (kry_waveform_get_type ()));
337 
338   if(color_table)
339   {
340     waveform->color_table = color_table;
341     color_table->Ref();
342     waveform->signal_color_change =
343       color_table->ConnectSignal(kryColorTable::SIGNAL_COLOR_CHANGED, (krySignalFunc1) kry_waveform_color_changed, waveform);
344   }
345   else
346   {
347     waveform->color_table = new kryColorTable(WAVEFORM_COLOR_COUNT);
348     waveform->color_table->Set(WAVEFORM_COLOR_LINE, "WaveformLine", __("Color|Line"), 0, 0xAA, 0);
349     waveform->color_table->Set(WAVEFORM_COLOR_SELECTION_HIGHLIGHT, "WaveformSelectionHighlight", __("Color|Selection Highlight"), 0xC0, 0xFF, 0);
350     waveform->color_table->Set(WAVEFORM_COLOR_SILENCE_HIGHLIGHT, "WaveformSilenceHighlight", __("Color|Silence Highlight"), 0, 0x66, 0);
351     waveform->color_table->Set(WAVEFORM_COLOR_MARKER_START, "WaveformMarkerStart", __("Color|Start Marker"), 0xAA, 0xAA, 0);
352     waveform->color_table->Set(WAVEFORM_COLOR_MARKER_END, "WaveformMarkerEnd", __("Color|End Marker"), 0xAA, 0, 0);
353     waveform->color_table->Set(WAVEFORM_COLOR_MARKER_KEYFRAME, "WaveformMarkerKeyframe", __("Color|Keyframe Marker"), 0xAA, 0xAA, 0xAA);
354     waveform->color_table->Set(WAVEFORM_COLOR_BACKGROUND, "WaveformBackground", __("Color|Background"), 0, 0, 0);
355     waveform->color_table->Set(WAVEFORM_COLOR_MARKER_TIME, "WaveformMarkerTime", __("Color|Time Marker"), 0, 0, 0x66);
356     waveform->color_table->Set(WAVEFORM_COLOR_MARKER_CURRENT, "WaveformMarkerCurrent", __("Color|Play Marker"), 0x33, 0xFF, 0x33);
357     waveform->color_table->Set(WAVEFORM_COLOR_TEXT, "WaveformText", __("Color|Text"), 0x55, 0xBB, 0xBB);
358     waveform->color_table->Set(WAVEFORM_COLOR_MARKER_KARAOKE, "WaveformMarkerKaraoke", __("Color|Karaoke Marker"), 0x66, 0x30, 0x66);
359     waveform->color_table->Set(WAVEFORM_COLOR_SCRUB_BAR_SEPARATOR, "WaveformScrubBarSeparator", __("Color|Scrub Bar Separator"), 0xFF, 0xFF, 0xFF);
360     waveform->color_table->Set(WAVEFORM_COLOR_SCRUB_BAR_SLIDER, "WaveformScrubBarSlider", __("Color|Scrub Bar Slider"), 0x00, 0x44, 0xFF);
361     waveform->color_table->Set(WAVEFORM_COLOR_SCRUB_BAR_EXTENSION, "WaveformScrubBarExtension", __("Color|Scrub Bar Extension"), 0x00, 0x88, 0x00);
362     waveform->signal_color_change =
363       waveform->color_table->ConnectSignal(kryColorTable::SIGNAL_COLOR_CHANGED, (krySignalFunc1) kry_waveform_color_changed, waveform);
364 
365 #ifdef _WINDOWS
366     for(int i = 0; i < WAVEFORM_COLOR_COUNT; i++)
367     {
368       kryColor *color = waveform->color_table->Get(i);
369       if(color->IsInitialized())
370       {
371         HPEN pen = CreatePen(PS_SOLID, 1, RGB(color->GetRed(), color->GetGreen(), color->GetBlue()));
372         color->SetUserData(pen);
373       }
374     }
375 #else
376     for(int i = 0; i < WAVEFORM_COLOR_COUNT; i++)
377     {
378       kryColor *color = waveform->color_table->Get(i);
379 
380       if(color->IsInitialized())
381       {
382         GdkColor *color_gdk = kry_new0(GdkColor);
383 
384         color_gdk->red = color->GetRed() * 257;
385         color_gdk->green = color->GetGreen() * 257;
386         color_gdk->blue = color->GetBlue() * 257;
387 
388         gdk_rgb_find_color(gtk_widget_get_colormap(GTK_WIDGET(waveform)), color_gdk);
389 
390         color->SetUserData(color_gdk);
391       }
392     }
393 #endif
394   }
395 
396 #ifdef _WINDOWS
397   kryColor *background = waveform->color_table->Get(WAVEFORM_COLOR_BACKGROUND);
398   waveform->black_brush = CreateSolidBrush(RGB(background->GetRed(), background->GetGreen(), background->GetBlue()));
399 
400   waveform->cursor_normal = LoadCursor(NULL, IDC_ARROW);
401   waveform->cursor_drag = LoadCursor(NULL, IDC_SIZEWE);
402 #else
403   waveform->cursor_drag = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
404   waveform->layout = PANGO_LAYOUT(gtk_widget_create_pango_layout(GTK_WIDGET(waveform), NULL));
405   PangoFontDescription *desc = pango_font_description_from_string("Arial 10");
406   pango_layout_set_font_description(waveform->layout, desc);
407 #endif
408 
409 
410   waveform->data_info = info;
411 
412   if(adjustment)
413     kry_waveform_set_adjustment(waveform, adjustment);
414 
415   g_object_set(waveform, "can-focus", TRUE, NULL);
416   gtk_widget_set_double_buffered(GTK_WIDGET(waveform), FALSE);
417 
418   return GTK_WIDGET (waveform);
419 }
420 
kry_waveform_destroy_graphics(KryWaveform * waveform)421 static void kry_waveform_destroy_graphics(KryWaveform *waveform)
422 {
423 #ifdef _WINDOWS
424   if(waveform->bitmap_backbuffer_waveonly)
425   {
426     if(!DeleteObject(waveform->bitmap_backbuffer_waveonly))
427       g_warning("failed to delete backbuffer bitmap");
428 
429     waveform->bitmap_backbuffer_waveonly = NULL;
430   }
431 
432   if(waveform->backbuffer_waveonly)
433   {
434     if(!DeleteDC(waveform->backbuffer_waveonly))
435       g_warning("failed to delete backbuffer");
436 
437     waveform->backbuffer_waveonly = NULL;
438   }
439 
440   if(waveform->bitmap_backbuffer_final)
441   {
442     if(!DeleteObject(waveform->bitmap_backbuffer_final))
443       g_warning("failed to delete backbuffer copy bitmap");
444 
445     waveform->bitmap_backbuffer_final = NULL;
446   }
447 
448   if(waveform->backbuffer_final)
449   {
450     if(!DeleteDC(waveform->backbuffer_final))
451       g_warning("failed to delete backbuffer copy");
452 
453     waveform->backbuffer_final = NULL;
454   }
455 
456   if(waveform->dc)
457   {
458     ReleaseDC(HWND(GDK_WINDOW_HWND(GTK_WIDGET(waveform)->window)), waveform->dc);
459     waveform->dc = NULL;
460   }
461 
462   if(waveform->font)
463   {
464     if(!DeleteObject(waveform->font))
465       g_warning("failed to delete font");
466 
467     waveform->font = NULL;
468   }
469 
470 #else
471   if(waveform->backbuffer_waveonly)
472   {
473     g_object_unref(waveform->backbuffer_waveonly);
474     waveform->backbuffer_waveonly = NULL;
475   }
476 
477   if(waveform->backbuffer_final)
478   {
479     g_object_unref(waveform->backbuffer_final);
480     waveform->backbuffer_final = NULL;
481   }
482 
483   if(waveform->gc)
484   {
485     g_object_unref(waveform->gc);
486     waveform->gc = NULL;
487   }
488 #endif
489 }
490 
kry_waveform_destroy(GtkObject * object)491 static void kry_waveform_destroy(GtkObject *object)
492 {
493   KryWaveform *waveform;
494 
495   g_return_if_fail (object != NULL);
496   g_return_if_fail (KRY_IS_WAVEFORM (object));
497 
498   waveform = KRY_WAVEFORM (object);
499 
500   if (GTK_OBJECT_CLASS (parent_class)->destroy)
501     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
502 
503 
504   if(waveform->adjustment)
505   {
506     g_signal_handlers_disconnect_by_func(waveform->adjustment, (void *) kry_waveform_adjustment_value_changed, waveform);
507     g_object_unref(waveform->adjustment);
508     waveform->adjustment = NULL;
509   }
510 
511   //if(waveform->mutex_markers)
512   //{
513     kry_waveform_marker_remove_all(waveform);
514 
515     if(waveform->region_list)
516     {
517       kry_waveform_region_remove_all(waveform);
518       waveform->region_list = NULL;
519     }
520 
521   //  g_mutex_free(waveform->mutex_markers);
522   //  waveform->mutex_markers = NULL;
523   //}
524 
525   kry_waveform_destroy_graphics(waveform);
526 
527 #ifdef _WINDOWS
528   int i;
529 
530   if(waveform->color_table)
531   {
532     waveform->color_table->DisconnectSignal(kryColorTable::SIGNAL_COLOR_CHANGED, waveform->signal_color_change);
533     if(waveform->color_table->GetRefCount() == 1)
534     {
535       for(i = 0; i < WAVEFORM_COLOR_COUNT; i++)
536       {
537         if(waveform->color_table->GetUserData(i) != NULL)
538         {
539           DeleteObject(waveform->color_table->GetUserData(i));
540           waveform->color_table->SetUserData(i, NULL);
541         }
542       }
543 
544       delete waveform->color_table;
545     }
546     else
547     {
548       waveform->color_table->Unref();
549     }
550 
551     waveform->color_table = NULL;
552   }
553 
554   if(waveform->black_brush)
555   {
556     DeleteObject(waveform->black_brush);
557     waveform->black_brush = NULL;
558   }
559 #else
560   if(waveform->layout)
561   {
562     g_object_unref(waveform->layout);
563     waveform->layout = NULL;
564   }
565 #endif
566   kry_waveform_data_thread_end(waveform);
567   if(waveform->data_pixel)
568   {
569     kry_free(waveform->data_pixel);
570     waveform->data_pixel = NULL;
571   }
572 
573   if(waveform->data_time)
574   {
575     kry_free(waveform->data_time);
576     waveform->data_time = NULL;
577   }
578 
579   kry_waveform_region_fixed_list_set(waveform, NULL);
580 }
581 
582 
583 GtkAdjustment*
kry_waveform_get_adjustment(KryWaveform * waveform)584 kry_waveform_get_adjustment (KryWaveform *waveform)
585 {
586   g_return_val_if_fail (waveform != NULL, NULL);
587   g_return_val_if_fail (KRY_IS_WAVEFORM (waveform), NULL);
588 
589   return waveform->adjustment;
590 }
591 
kry_waveform_marker_redraw_at_time(KryWaveform * waveform,long time_mili,gboolean no_update=FALSE)592 void kry_waveform_marker_redraw_at_time(KryWaveform *waveform, long time_mili, gboolean no_update = FALSE)
593 {
594   if(time_mili == -1 || waveform->data_info == NULL)
595     return;
596 
597   int start = kry_waveform_rel_pixel_from_mili(waveform, time_mili);
598   int width = waveform->marker_width + waveform->corner_width;
599 
600   kry_waveform_redraw_partial(waveform, start, width, FALSE, !no_update);
601 }
602 
kry_waveform_marker_changed_cb(KryMarker * marker,int old_position,KryWaveform * waveform)603 void kry_waveform_marker_changed_cb(KryMarker *marker, int old_position, KryWaveform *waveform)
604 {
605   g_return_if_fail (waveform != NULL);
606   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
607 
608   if(!waveform->data_info)
609     return;
610 
611   if(g_object_get_data(G_OBJECT(marker), "highlight"))
612     return;
613 
614   int pos1 = kry_waveform_rel_pixel_from_mili(waveform, kry_marker_get_value(marker));
615   int pos2 = kry_waveform_rel_pixel_from_mili(waveform, old_position);
616   int width = waveform->marker_width + 10;
617 
618   kry_waveform_redraw_partial(waveform, pos1, width, FALSE, FALSE);
619   kry_waveform_redraw_partial(waveform, pos2, width, FALSE, FALSE);
620 
621   kry_waveform_update_front_buffer_fast(waveform, pos1, width);
622   kry_waveform_update_front_buffer_fast(waveform, pos2, width);
623 
624   if(waveform->marker_autoscroll == marker)
625   {
626     if((pos1 * 100) / GTK_WIDGET(waveform)->allocation.width > 90)
627     {
628       int page_increment = (int) waveform->adjustment->page_increment;
629       int val = (int) (gtk_adjustment_get_value(waveform->adjustment) + page_increment);
630       gtk_adjustment_set_value(waveform->adjustment, val);
631     }
632   }
633 }
634 
kry_waveform_highlight_marker_changed(KryMarker * marker,long old_position,KryWaveform * waveform)635 void kry_waveform_highlight_marker_changed(KryMarker *marker, long old_position, KryWaveform *waveform)
636 {
637   GtkWidget *widget;
638   int start_pixel, end_pixel;
639 
640   g_return_if_fail (waveform != NULL);
641   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
642 
643   if(waveform->data_info == NULL)
644     return;
645 
646   if(old_position == -1)
647   {
648     kry_waveform_redraw(waveform);
649     return;
650   }
651 
652   if(kry_marker_get_value(marker) == -1)
653     start_pixel = 0;
654   else
655     start_pixel = kry_waveform_rel_pixel_from_mili(waveform, kry_marker_get_value(marker));
656 
657   if(old_position == -1)
658     end_pixel = 0;
659   else
660     end_pixel = kry_waveform_rel_pixel_from_mili(waveform, old_position);
661 
662   if(start_pixel > end_pixel)
663   {
664     int tmp = start_pixel;
665     start_pixel = end_pixel;
666     end_pixel = tmp;
667   }
668 
669   widget = GTK_WIDGET(waveform);
670   if(start_pixel + waveform->marker_width + waveform->corner_width < 0 && end_pixel + waveform->marker_width + waveform->corner_width < 0
671     || start_pixel > widget->allocation.width && end_pixel > widget->allocation.width)
672   {
673     return;
674   }
675 
676   if(start_pixel < 0)
677     start_pixel = 0;
678 
679   if(end_pixel >= widget->allocation.width)
680     end_pixel = widget->allocation.width - 1;
681 
682   kry_waveform_redraw_partial(waveform,
683     start_pixel - waveform->corner_width,
684     end_pixel + waveform->marker_width + waveform->corner_width * 2 - start_pixel, FALSE, TRUE);
685 }
686 
kry_waveform_region_add_new(KryWaveform * waveform,KryMarker * marker_left,KryMarker * marker_right,int color_id)687 void kry_waveform_region_add_new(KryWaveform *waveform, KryMarker *marker_left, KryMarker *marker_right, int color_id)
688 {
689   g_return_if_fail (waveform != NULL);
690   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
691 
692   KryRegion *region = KRY_REGION(kry_region_new(marker_left, marker_right, color_id));
693   kry_waveform_region_add(waveform, region);
694 }
695 
kry_waveform_region_add(KryWaveform * waveform,KryRegion * region)696 void kry_waveform_region_add(KryWaveform *waveform, KryRegion *region)
697 {
698   g_return_if_fail (waveform != NULL);
699   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
700 
701   g_object_ref(region);
702 
703   int color_id = kry_region_get_colorid(region);
704   if(color_id != -1)
705   {
706     g_object_set_data(G_OBJECT(kry_region_get_marker_start(region)), "highlight", (gpointer) TRUE);
707     g_object_set_data(G_OBJECT(kry_region_get_marker_end(region)), "highlight", (gpointer) TRUE);
708 
709     g_signal_connect(kry_region_get_marker_start(region), "value-changed", G_CALLBACK(kry_waveform_highlight_marker_changed), waveform);
710     g_signal_connect(kry_region_get_marker_end(region), "value-changed", G_CALLBACK(kry_waveform_highlight_marker_changed), waveform);
711   }
712 
713   waveform->region_list = g_list_append(waveform->region_list, region);
714 
715   if(color_id != -1 && waveform->data_info)
716   {
717     KryMarker *m1 = kry_region_get_marker_start(region);
718     KryMarker *m2 = kry_region_get_marker_end(region);
719     int px1 = kry_waveform_rel_pixel_from_mili(waveform, kry_marker_get_value(m1));
720     int px2 = kry_waveform_rel_pixel_from_mili(waveform, kry_marker_get_value(m2));
721 
722     if(px1 <= GTK_WIDGET(waveform)->allocation.width - 1 && px2 >= 0 && px1 <= px2)
723       kry_waveform_redraw_partial(waveform, px1, px2 + waveform->marker_width - 1, FALSE, TRUE);
724   }
725 }
726 
kry_waveform_region_fixed_added_cb(KryRegionFixedList * list,KryRegionFixed * region,KryWaveform * waveform)727 static void kry_waveform_region_fixed_added_cb(KryRegionFixedList *list, KryRegionFixed *region, KryWaveform *waveform)
728 {
729   g_return_if_fail (waveform != NULL);
730   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
731 
732 
733   if(!waveform->data_info)
734     return;
735 
736   if(pavl_count(waveform->region_fixed_list->tree) == 1)
737     pavl_t_first(&waveform->region_fixed_list_iter, waveform->region_fixed_list->tree);
738 
739   int px1 = kry_waveform_rel_pixel_from_mili(waveform, region->start);
740   int px2 = kry_waveform_rel_pixel_from_mili(waveform, region->end);
741 
742   if(px1 <= GTK_WIDGET(waveform)->allocation.width - 1 && px2 >= 0 && px1 <= px2)
743   {
744     struct KryRegionFixedInfo *info = (struct KryRegionFixedInfo *) pavl_t_cur(&waveform->region_fixed_list_iter);
745     if(info)
746     {
747       struct KryRegionFixed *region_cur = (struct KryRegionFixed *) info->regions->data;
748       if(region_cur->start > region->start)
749         pavl_t_prev(&waveform->region_fixed_list_iter);
750     };
751     kry_waveform_redraw_partial(waveform, px1, px2 + waveform->marker_width - 1, FALSE, TRUE);
752   }
753 }
754 
kry_waveform_region_fixed_removed_cb(KryRegionFixedList * list,KryRegionFixed * region,KryWaveform * waveform)755 static void kry_waveform_region_fixed_removed_cb(KryRegionFixedList *list, KryRegionFixed *region, KryWaveform *waveform)
756 {
757   g_return_if_fail (waveform != NULL);
758   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
759 
760   if(!waveform->data_info)
761     return;
762 
763   pavl_t_first(&waveform->region_fixed_list_iter, waveform->region_fixed_list->tree);
764   kry_waveform_find_first_region(waveform, FALSE);
765 
766   int px1 = kry_waveform_rel_pixel_from_mili(waveform, region->start);
767   int px2 = kry_waveform_rel_pixel_from_mili(waveform, region->end);
768 
769   if(px1 <= GTK_WIDGET(waveform)->allocation.width - 1 && px2 >= 0 && px1 <= px2)
770     kry_waveform_redraw_partial(waveform, px1, px2 + waveform->marker_width - 1, FALSE, TRUE);
771 }
772 
kry_waveform_region_fixed_list_set(KryWaveform * waveform,KryRegionFixedList * list)773 void kry_waveform_region_fixed_list_set(KryWaveform *waveform, KryRegionFixedList *list)
774 {
775   g_return_if_fail (waveform != NULL);
776   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
777 
778   if(waveform->region_fixed_list)
779   {
780     g_signal_handlers_disconnect_by_func(waveform->region_fixed_list, (void *) kry_waveform_region_fixed_added_cb, waveform);
781     g_signal_handlers_disconnect_by_func(waveform->region_fixed_list, (void *) kry_waveform_region_fixed_removed_cb, waveform);
782 
783     waveform->region_fixed_list = NULL;
784   }
785 
786   if(list)
787   {
788     waveform->region_fixed_list = list;
789     pavl_t_first(&waveform->region_fixed_list_iter, waveform->region_fixed_list->tree);
790 
791     g_signal_connect(list, "region-added", (GCallback) kry_waveform_region_fixed_added_cb, waveform);
792     g_signal_connect(list, "region-removed", (GCallback) kry_waveform_region_fixed_removed_cb, waveform);
793   }
794 
795   kry_waveform_redraw(waveform);
796 }
797 
798 
kry_waveform_region_remove_by_type(KryWaveform * waveform,int color_id)799 void kry_waveform_region_remove_by_type(KryWaveform *waveform, int color_id)
800 {
801   GList *ptr_next;
802   g_return_if_fail (waveform != NULL);
803   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
804 
805   for(GList *ptr = waveform->region_list; ptr; ptr = ptr_next)
806   {
807     ptr_next = ptr->next;
808 
809     KryRegion *region = (KryRegion *) ptr->data;
810     if(color_id != -1 && kry_region_get_colorid(region) != color_id)
811       continue;
812 
813     g_signal_handlers_disconnect_by_func(kry_region_get_marker_start(region), (void *) kry_waveform_highlight_marker_changed, waveform);
814     g_signal_handlers_disconnect_by_func(kry_region_get_marker_end(region), (void *) kry_waveform_highlight_marker_changed, waveform);
815 
816     g_object_set_data(G_OBJECT(kry_region_get_marker_start(region)), "highlight", (gpointer) FALSE);
817     g_object_set_data(G_OBJECT(kry_region_get_marker_end(region)), "highlight", (gpointer) FALSE);
818 
819     waveform->region_list = g_list_remove(waveform->region_list, region);
820     g_object_unref(G_OBJECT(region));
821   }
822 }
823 
kry_waveform_region_remove_all(KryWaveform * waveform)824 void kry_waveform_region_remove_all(KryWaveform *waveform)
825 {
826   kry_waveform_region_remove_by_type(waveform, -1);
827 }
828 
kry_waveform_marker_add(KryWaveform * waveform,KryMarker * marker)829 void kry_waveform_marker_add(KryWaveform *waveform, KryMarker *marker)
830 {
831   g_return_if_fail (waveform != NULL);
832   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
833 
834   struct KryWaveformMarkerInfo *marker_info = kry_new(struct KryWaveformMarkerInfo, 1);
835   marker_info->marker = marker;
836 
837   //g_mutex_lock(waveform->mutex_markers);
838   waveform->markers = g_list_append(waveform->markers, marker_info);
839   g_signal_connect(marker, "value-changed", G_CALLBACK(kry_waveform_marker_changed_cb), waveform);
840 
841   // this forces the marker area to be redrawn
842   kry_waveform_marker_redraw_at_time(waveform, kry_marker_get_value(marker));
843   //g_mutex_unlock(waveform->mutex_markers);
844 }
845 
kry_waveform_marker_hide(KryWaveform * waveform,KryMarker * marker)846 void kry_waveform_marker_hide(KryWaveform *waveform, KryMarker *marker)
847 {
848   g_return_if_fail (waveform != NULL);
849   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
850 
851   g_object_set_data(G_OBJECT(marker), "hidden", (gpointer) 1);
852 
853   kry_waveform_marker_redraw_at_time(waveform, kry_marker_get_value(marker));
854 }
855 
856 
kry_waveform_marker_show(KryWaveform * waveform,KryMarker * marker)857 void kry_waveform_marker_show(KryWaveform *waveform, KryMarker *marker)
858 {
859   g_return_if_fail (waveform != NULL);
860   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
861 
862   g_object_set_data(G_OBJECT(marker), "hidden", 0);
863 
864   kry_waveform_marker_redraw_at_time(waveform, kry_marker_get_value(marker));
865 }
866 
kry_waveform_marker_remove_internal(KryWaveform * waveform,KryMarker * marker_match,enum marker_type type,gboolean remove_all)867 static void kry_waveform_marker_remove_internal(KryWaveform *waveform, KryMarker *marker_match, enum marker_type type, gboolean remove_all)
868 {
869   GList *ptr;
870   GList *next = NULL;
871   g_return_if_fail (waveform != NULL);
872   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
873 
874   //g_mutex_lock(waveform->mutex_markers);
875   for(ptr = waveform->markers; ptr; ptr = next)
876   {
877     struct KryWaveformMarkerInfo *info =  (struct KryWaveformMarkerInfo *) ptr->data;
878     KryMarker *marker = info->marker;
879     next = ptr->next;
880     if(marker_match && marker == marker_match || kry_marker_get_marker_type(marker) == type || remove_all)
881     {
882       if(waveform->marker_active_start == marker)
883         kry_waveform_marker_set_active_start(waveform, NULL);
884 
885       if(waveform->marker_active_end == marker)
886         kry_waveform_marker_set_active_end(waveform, NULL);
887 
888       g_signal_handlers_disconnect_by_func(marker, (void *) kry_waveform_marker_changed_cb, waveform);
889       waveform->markers = g_list_delete_link(waveform->markers, ptr);
890 
891       kry_waveform_marker_redraw_at_time(waveform, kry_marker_get_value(marker));
892     }
893   }
894   //g_mutex_unlock(waveform->mutex_markers);
895 }
896 
kry_waveform_marker_remove_by_type(KryWaveform * waveform,enum marker_type type)897 void kry_waveform_marker_remove_by_type(KryWaveform *waveform, enum marker_type type)
898 {
899   kry_waveform_marker_remove_internal(waveform, NULL, type, FALSE);
900 }
901 
kry_waveform_marker_remove(KryWaveform * waveform,KryMarker * marker)902 void kry_waveform_marker_remove(KryWaveform *waveform, KryMarker *marker)
903 {
904   kry_waveform_marker_remove_internal(waveform, marker, (enum marker_type) 0, FALSE);
905 }
906 
kry_waveform_marker_remove_all(KryWaveform * waveform)907 void kry_waveform_marker_remove_all(KryWaveform *waveform)
908 {
909   kry_waveform_marker_remove_internal(waveform, NULL, (enum marker_type) 0, TRUE);
910 }
911 
kry_waveform_marker_set_autoscroll(KryWaveform * waveform,KryMarker * marker)912 void kry_waveform_marker_set_autoscroll(KryWaveform *waveform, KryMarker *marker)
913 {
914   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
915 
916   waveform->marker_autoscroll = marker;
917 }
918 
kry_waveform_get_show_time_bar(KryWaveform * waveform)919 gboolean kry_waveform_get_show_time_bar(KryWaveform *waveform)
920 {
921   g_return_val_if_fail (waveform != NULL, FALSE);
922   g_return_val_if_fail (KRY_IS_WAVEFORM (waveform), FALSE);
923 
924   return waveform->show_time_bar;
925 }
926 
kry_waveform_get_show_keyframes(KryWaveform * waveform)927 gboolean kry_waveform_get_show_keyframes(KryWaveform *waveform)
928 {
929   g_return_val_if_fail (waveform != NULL, FALSE);
930   g_return_val_if_fail (KRY_IS_WAVEFORM (waveform), FALSE);
931 
932   return waveform->show_keyframe;
933 }
934 
kry_waveform_set_show_scrub_bar(KryWaveform * waveform,gboolean val)935 void kry_waveform_set_show_scrub_bar(KryWaveform *waveform, gboolean val)
936 {
937   g_return_if_fail (waveform != NULL);
938   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
939 
940   if(waveform->show_scrub_bar == val)
941     return;
942 
943   if(val)
944     waveform->scrub_bar_height = waveform->scrub_bar_height_real;
945   else
946     waveform->scrub_bar_height = 0;
947 
948   waveform->wave_height = GTK_WIDGET(waveform)->allocation.height - waveform->time_bar_height - waveform->scrub_bar_height;
949   waveform->show_scrub_bar = val;
950 
951   kry_waveform_redraw(waveform);
952 }
953 
kry_waveform_set_show_time_bar(KryWaveform * waveform,gboolean val)954 void kry_waveform_set_show_time_bar(KryWaveform *waveform, gboolean val)
955 {
956   g_return_if_fail (waveform != NULL);
957   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
958 
959   if(waveform->show_time_bar == val)
960     return;
961 
962   if(val)
963     waveform->time_bar_height = waveform->time_bar_height_real;
964   else
965     waveform->time_bar_height = 0;
966 
967   waveform->wave_height = GTK_WIDGET(waveform)->allocation.height - waveform->time_bar_height - waveform->scrub_bar_height;
968   waveform->show_time_bar = val;
969 
970   kry_waveform_redraw(waveform);
971 }
972 
kry_waveform_set_show_time_markers(KryWaveform * waveform,gboolean val)973 void kry_waveform_set_show_time_markers(KryWaveform *waveform, gboolean val)
974 {
975   g_return_if_fail (waveform != NULL);
976   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
977 
978   if(waveform->show_time_markers == val)
979     return;
980 
981   waveform->show_time_markers = val;
982 
983   kry_waveform_redraw(waveform);
984 }
985 
kry_waveform_set_show_keyframes(KryWaveform * waveform,gboolean val)986 void kry_waveform_set_show_keyframes(KryWaveform *waveform, gboolean val)
987 {
988   g_return_if_fail (waveform != NULL);
989   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
990 
991   waveform->show_keyframe = val;
992 
993   kry_waveform_redraw(waveform);
994 }
995 
kry_waveform_set_adjustment(KryWaveform * waveform,GtkAdjustment * adjustment)996 void kry_waveform_set_adjustment (KryWaveform *waveform, GtkAdjustment *adjustment)
997 {
998   g_return_if_fail (waveform != NULL);
999   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
1000 
1001   if(waveform->adjustment)
1002   {
1003     g_signal_handlers_disconnect_by_func(waveform->adjustment, (void *) kry_waveform_adjustment_value_changed, waveform);
1004     g_object_unref (GTK_OBJECT (waveform->adjustment));
1005   }
1006 
1007   waveform->adjustment = adjustment;
1008   g_object_ref(adjustment);
1009   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
1010 		    (GtkSignalFunc) kry_waveform_adjustment_value_changed,
1011 		    (gpointer) waveform);
1012 
1013   kry_waveform_adjustment_value_changed(adjustment, waveform);
1014 }
1015 
1016 static void
kry_waveform_realize(GtkWidget * widget)1017 kry_waveform_realize (GtkWidget *widget)
1018 {
1019   KryWaveform *waveform;
1020   GdkWindowAttr attributes;
1021   gint attributes_mask;
1022 
1023   g_return_if_fail (widget != NULL);
1024   g_return_if_fail (KRY_IS_WAVEFORM (widget));
1025 
1026   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1027   waveform = KRY_WAVEFORM (widget);
1028 
1029   attributes.x = widget->allocation.x;
1030   attributes.y = widget->allocation.y;
1031   attributes.width = widget->allocation.width;
1032   attributes.height = widget->allocation.height;
1033   attributes.wclass = GDK_INPUT_OUTPUT;
1034   attributes.window_type = GDK_WINDOW_CHILD;
1035   attributes.event_mask = gtk_widget_get_events (widget) |
1036     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
1037     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK;
1038   attributes.visual = gtk_widget_get_visual (widget);
1039   attributes.colormap = gtk_widget_get_colormap (widget);
1040 
1041   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1042   widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
1043 
1044 #ifdef _WINDOWS
1045   waveform->dc = GetDC(HWND(GDK_WINDOW_HWND(widget->window)));
1046 #else
1047   waveform->gc = gdk_gc_new(widget->window);
1048 #endif
1049 
1050   widget->style = gtk_style_attach (widget->style, widget->window);
1051 
1052   gdk_window_set_user_data (widget->window, widget);
1053 
1054   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
1055 
1056   if(!waveform->backbuffer_waveonly)
1057     kry_waveform_size_allocate(widget, &widget->allocation);
1058 }
1059 
1060 static void
kry_waveform_size_request(GtkWidget * widget,GtkRequisition * requisition)1061 kry_waveform_size_request (GtkWidget      *widget,
1062 		       GtkRequisition *requisition)
1063 {
1064   requisition->width = 200;
1065   requisition->height = 80;
1066 }
1067 
1068 
1069 
1070 
kry_waveform_update_adjustment(KryWaveform * waveform)1071 void kry_waveform_update_adjustment(KryWaveform *waveform)
1072 {
1073   g_return_if_fail (waveform != NULL);
1074   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
1075 
1076   waveform->adjustment->step_increment = ((GTK_WIDGET(waveform)->allocation.width - 100) * waveform->data_per_pixel) / 10;
1077   waveform->adjustment->page_increment = ((GTK_WIDGET(waveform)->allocation.width - 100) * waveform->data_per_pixel);
1078   waveform->adjustment->upper =
1079     waveform->data_info->length_seconds * waveform->data_info->vals_per_sec;
1080   waveform->adjustment->page_size =
1081           (double) waveform->adjustment->upper * waveform->data_per_pixel
1082           * GTK_WIDGET(waveform)->allocation.width
1083           / (double) (waveform->data_info->length_seconds * waveform->data_info->vals_per_sec);
1084 
1085   g_signal_emit_by_name(G_OBJECT(waveform->adjustment), "changed");
1086 }
1087 
1088 void
kry_waveform_size_allocate(GtkWidget * widget,GtkAllocation * allocation)1089 kry_waveform_size_allocate (GtkWidget     *widget,
1090 			GtkAllocation *allocation)
1091 {
1092   KryWaveform *waveform;
1093 
1094   g_return_if_fail (widget != NULL);
1095   g_return_if_fail (KRY_IS_WAVEFORM (widget));
1096   g_return_if_fail (allocation != NULL);
1097 
1098   widget->allocation = *allocation;
1099 
1100   if (GTK_WIDGET_REALIZED (widget))
1101     {
1102 #ifdef _WINDOWS
1103       LOGFONT lfont;
1104 #endif
1105       waveform = KRY_WAVEFORM (widget);
1106 
1107       gdk_window_move_resize (widget->window,
1108 			      allocation->x, allocation->y,
1109 			      allocation->width, allocation->height);
1110 
1111       if(waveform->adjustment && waveform->data_info)
1112         kry_waveform_update_adjustment(waveform);
1113 
1114       kry_waveform_destroy_graphics(waveform);
1115 #ifdef _WINDOWS
1116       lfont.lfHeight = 14;
1117       lfont.lfWidth = 0;
1118       lfont.lfEscapement = 0;
1119       lfont.lfOrientation = 0;
1120       lfont.lfWeight = FW_NORMAL;
1121       lfont.lfItalic = 0;
1122       lfont.lfUnderline = 0;
1123       lfont.lfStrikeOut = 0;
1124       lfont.lfCharSet = ANSI_CHARSET;
1125       lfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
1126       lfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1127       // lfQuality Specifies the output quality. Use ANTIALIASED_QUALITY!
1128       lfont.lfQuality = ANTIALIASED_QUALITY;
1129       lfont.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
1130       lstrcpy(lfont.lfFaceName,"Arial");
1131       waveform->font = CreateFontIndirect(&lfont);
1132 
1133       if(!waveform->font)
1134         g_warning("failed to create font");
1135 
1136       waveform->dc = GetDC(HWND(GDK_WINDOW_HWND(GTK_WIDGET(waveform)->window)));
1137       if(!waveform->dc)
1138         g_warning("failed to obtain waveform db");
1139 
1140       waveform->backbuffer_waveonly = CreateCompatibleDC(waveform->dc);
1141       if(!waveform->backbuffer_waveonly)
1142         g_warning("failed to create backbuffer");
1143 
1144       waveform->backbuffer_final = CreateCompatibleDC(waveform->dc);
1145       if(!waveform->backbuffer_final)
1146         g_warning("failed to create backbuffer copy");
1147 
1148       waveform->bitmap_backbuffer_waveonly = CreateCompatibleBitmap (waveform->dc, allocation->width, allocation->height);
1149       if(!waveform->bitmap_backbuffer_waveonly)
1150         g_warning("failed to create backbuffer bitmap");
1151 
1152       if(!SelectObject (waveform->backbuffer_waveonly, waveform->bitmap_backbuffer_waveonly))
1153         g_warning("failed to select backbuffer bitmap");
1154 
1155       waveform->bitmap_backbuffer_final = CreateCompatibleBitmap (waveform->dc, allocation->width, allocation->height);
1156       if(!waveform->bitmap_backbuffer_final)
1157         g_warning("failed to create backbuffer copy bitmap");
1158 
1159       if(!SelectObject (waveform->backbuffer_final, waveform->bitmap_backbuffer_final))
1160         g_warning("failed to select backbuffer bitmap copy");
1161 
1162       if(!SelectObject(waveform->backbuffer_waveonly, waveform->font))
1163         g_warning("failed to select font");
1164 
1165       if(!SetBkMode(waveform->backbuffer_waveonly, TRANSPARENT))
1166         g_warning("failed to set background mode");
1167 
1168 
1169       TEXTMETRIC metric;
1170       GetTextMetrics(waveform->backbuffer_final, &metric);
1171       waveform->time_bar_height_real = metric.tmHeight;
1172 #else
1173      PangoContext *context = pango_layout_get_context(waveform->layout);
1174      PangoFontDescription *desc = (PangoFontDescription *) pango_layout_get_font_description(waveform->layout);
1175      PangoFontMetrics *metrics = pango_context_get_metrics(context, desc, NULL);
1176      waveform->backbuffer_waveonly = gdk_pixmap_new(widget->window, allocation->width, allocation->height, -1);
1177      waveform->backbuffer_final = gdk_pixmap_new(waveform->backbuffer_waveonly, allocation->width, allocation->height, -1);
1178      waveform->gc = gdk_gc_new(widget->window);
1179      waveform->time_bar_height_real = (pango_font_metrics_get_ascent(metrics) + pango_font_metrics_get_descent(metrics)) / PANGO_SCALE;
1180 
1181 #endif
1182       if(waveform->show_time_bar)
1183         waveform->time_bar_height = waveform->time_bar_height_real;
1184 
1185       waveform->wave_height = allocation->height - waveform->time_bar_height - waveform->scrub_bar_height;
1186 
1187       kry_waveform_update_zoom(waveform);
1188 
1189       double min_zoom = kry_waveform_get_zoom_min(waveform);
1190       if(fabs(min_zoom - waveform->min_zoom) > 0.0001)
1191       {
1192         waveform->min_zoom = min_zoom;
1193         g_signal_emit(waveform, kry_waveform_signals[MIN_ZOOM_CHANGED_SIGNAL], 0, min_zoom);
1194       }
1195 
1196       kry_waveform_redraw(waveform);
1197   }
1198 }
1199 
1200 
1201 
1202 static gboolean
kry_waveform_key_press(GtkWidget * widget,GdkEventKey * event)1203 kry_waveform_key_press( GtkWidget      *widget,
1204 		       GdkEventKey *event )
1205 {
1206   KryWaveform *waveform;
1207 
1208   g_return_val_if_fail (widget != NULL, FALSE);
1209   g_return_val_if_fail (KRY_IS_WAVEFORM (widget), FALSE);
1210   g_return_val_if_fail (event != NULL, FALSE);
1211 
1212   waveform = KRY_WAVEFORM (widget);
1213 
1214   return TRUE;
1215 }
1216 
kry_waveform_is_over_marker(KryWaveform * waveform,KryMarker * marker,int x)1217 static gboolean kry_waveform_is_over_marker(KryWaveform *waveform, KryMarker *marker, int x)
1218 {
1219   int marker_pos = kry_waveform_rel_pixel_from_mili(waveform, kry_marker_get_value(marker));
1220 
1221   if(x >= marker_pos - 3 && x <= marker_pos + 4)
1222     return TRUE;
1223   else
1224     return FALSE;
1225 }
1226 
1227 
1228 static gboolean
kry_waveform_button_press(GtkWidget * widget,GdkEventButton * event)1229 kry_waveform_button_press( GtkWidget      *widget,
1230 		       GdkEventButton *event )
1231 {
1232   KryWaveform *waveform;
1233 
1234   g_return_val_if_fail (widget != NULL, FALSE);
1235   g_return_val_if_fail (KRY_IS_WAVEFORM (widget), FALSE);
1236   g_return_val_if_fail (event != NULL, FALSE);
1237 
1238   waveform = KRY_WAVEFORM (widget);
1239 
1240   if(!waveform->data_info)
1241     return FALSE;
1242 
1243   waveform->button_press = TRUE;
1244 
1245   if(event->button == 2)
1246     return FALSE;
1247 
1248   if(!GTK_WIDGET_HAS_FOCUS(widget))
1249     gtk_widget_grab_focus(widget);
1250 
1251   if(event->y < waveform->scrub_bar_height)
1252   {
1253     if(event->x >= waveform->scrub_bar_left_ext && event->x <= waveform->scrub_bar_right_ext)
1254     {
1255       waveform->is_scrub_bar_dragging = TRUE;
1256       waveform->scrub_bar_drag_offset = (int) event->x - waveform->scrub_bar_left;
1257     }
1258 
1259     return FALSE;
1260   }
1261 
1262   // user clicked on the start marker
1263   if(waveform->drag_markers_enabled && waveform->marker_active_start
1264      && kry_waveform_is_over_marker(waveform, waveform->marker_active_start, (int) event->x))
1265   {
1266     waveform->marker_dragging = waveform->marker_active_start;
1267   }
1268 
1269   // user clicked on the end marker
1270   if(waveform->drag_markers_enabled && !waveform->marker_dragging
1271      && waveform->marker_active_end && kry_waveform_is_over_marker(waveform, waveform->marker_active_end, (int) event->x))
1272   {
1273     waveform->marker_dragging = waveform->marker_active_end;
1274   }
1275 
1276   // user didn't click on a marker (he either wants to put the start marker there, or he wants to create a selection by dragging)
1277   if(!waveform->marker_dragging && event->button == 1 && waveform->marker_active_start)
1278   {
1279     int mili = kry_waveform_mili_from_rel_pixel(waveform, (int) event->x);
1280     kry_marker_set_value(waveform->marker_active_start, mili);
1281 
1282     if(waveform->drag_selection_enabled && waveform->drag_markers_enabled)
1283     {
1284       waveform->marker_dragging = waveform->marker_active_end;
1285       waveform->drag_select = TRUE;
1286     }
1287     else
1288     {
1289       waveform->marker_dragging = waveform->marker_active_start;
1290     }
1291   }
1292 
1293   if(waveform->drag_markers_enabled && waveform->marker_dragging)
1294   {
1295 #ifdef _WINDOWS
1296     SetCursor(waveform->cursor_drag);
1297 #endif
1298     return FALSE;
1299   }
1300 
1301   if(event->button == 3 && waveform->marker_active_end)
1302   {
1303     int mili = kry_waveform_mili_from_rel_pixel(waveform, (int) event->x);
1304     kry_marker_set_value(waveform->marker_active_end, mili);
1305 
1306     if(!waveform->drag_selection_enabled || !waveform->drag_markers_enabled)
1307       waveform->marker_dragging = waveform->marker_active_end;
1308   }
1309 
1310   return FALSE;
1311 }
1312 
1313 static gboolean
kry_waveform_motion_notify(GtkWidget * widget,GdkEventMotion * event)1314 kry_waveform_motion_notify( GtkWidget      *widget,
1315                         GdkEventMotion *event )
1316 {
1317   KryWaveform *waveform;
1318 
1319   g_return_val_if_fail (widget != NULL, FALSE);
1320   g_return_val_if_fail (KRY_IS_WAVEFORM (widget), FALSE);
1321   g_return_val_if_fail (event != NULL, FALSE);
1322 
1323   waveform = KRY_WAVEFORM (widget);
1324 
1325   if(!waveform->data_info)
1326     return FALSE;
1327 
1328   if(waveform->is_scrub_bar_dragging)
1329   {
1330     int left = (int) waveform->left;
1331     if(event->x < 0)
1332       event->x = 0;
1333 
1334     if(event->x >= GTK_WIDGET(waveform)->allocation.width)
1335       event->x = GTK_WIDGET(waveform)->allocation.width - 1;
1336 
1337     left = (int) ((event->x - waveform->scrub_bar_drag_offset) * (((double) waveform->data_info->length_seconds * waveform->data_info->vals_per_sec) / GTK_WIDGET(waveform)->allocation.width));
1338     if(left < 0)
1339       waveform->scrub_bar_drag_offset = (int) event->x;
1340 
1341     if(left >= waveform->adjustment->upper - waveform->adjustment->page_size)
1342     {
1343       left = (int) (waveform->adjustment->upper - waveform->adjustment->page_size);
1344       waveform->scrub_bar_drag_offset = waveform->scrub_bar_width - (GTK_WIDGET(waveform)->allocation.width - (int) event->x);
1345     }
1346 
1347     gtk_adjustment_set_value(waveform->adjustment, left);
1348 
1349     return FALSE;
1350   }
1351 
1352   // in the middle of a drag operation
1353   if(waveform->marker_dragging)
1354   {
1355     // if in the middle of a "drag to create a selection" operation
1356     if(waveform->drag_select)
1357     {
1358       // don't do anything unless the pointer has moved at least 10 pixels from the original location"
1359       int oldpx = kry_waveform_rel_pixel_from_mili(waveform, kry_marker_get_value(waveform->marker_active_start));
1360       if(abs((int) event->x - oldpx) < 10)
1361         return FALSE;
1362 
1363       waveform->drag_select = FALSE;
1364     }
1365 
1366     int marker_pixel = (int) event->x;
1367     int marker_mili = kry_waveform_mili_from_rel_pixel(waveform, marker_pixel);
1368 
1369     // if keyframes are on, see if there are any keyframes nearby
1370     if(waveform->show_keyframe)
1371     {
1372       for(int i = 0; i < waveform->keyframes_rel_count; i++)
1373       {
1374         int val = kry_waveform_rel_pixel_from_mili(waveform, waveform->keyframes_rel[i]);
1375         if(val - marker_pixel > 20)
1376           break;
1377 
1378         if(abs(val - marker_pixel) <= 20)
1379         {
1380           int mili = waveform->keyframes_rel[i];
1381 
1382           if(mili % 10 != 0)
1383             mili -= (mili % 10);
1384           mili -= 10;
1385 
1386           marker_mili = mili;
1387           break;
1388         }
1389       }
1390     }
1391 
1392     //g_warning("set value");
1393     kry_marker_set_value(waveform->marker_dragging, marker_mili);
1394     return FALSE;
1395   }
1396 
1397   if(event->y < waveform->scrub_bar_height)
1398     return FALSE;
1399 
1400   if(waveform->drag_markers_enabled &&
1401      (waveform->marker_active_start && kry_waveform_is_over_marker(waveform, waveform->marker_active_start, (int) event->x)
1402       ||waveform->marker_active_end && kry_waveform_is_over_marker(waveform, waveform->marker_active_end, (int) event->x)))
1403   {
1404 #ifdef _WINDOWS
1405     SetCursor(waveform->cursor_drag);
1406 #else
1407     gdk_window_set_cursor(widget->window, waveform->cursor_drag);
1408 #endif
1409   }
1410   else
1411   {
1412 #ifdef _WINDOWS
1413     SetCursor(waveform->cursor_normal);
1414 #else
1415     gdk_window_set_cursor(widget->window, NULL);
1416 #endif
1417   }
1418 
1419   return FALSE;
1420 }
1421 
1422 
1423 /*KryMarker *kry_waveform_get_marker(KryWaveform *waveform, enum marker_type type)
1424 {
1425   GList *ptr;
1426   g_return_val_if_fail (waveform != NULL, NULL);
1427   g_return_val_if_fail (KRY_IS_WAVEFORM (waveform), NULL);
1428 
1429   for(ptr = waveform->markers; ptr; ptr = ptr->next)
1430   {
1431     KryMarker *marker = KRY_MARKER(ptr->data);
1432     if(marker->type == type)
1433       return marker;
1434   }
1435 
1436   return NULL;
1437 }*/
1438 
kry_waveform_button_release(GtkWidget * widget,GdkEventButton * event)1439 static gboolean kry_waveform_button_release(GtkWidget *widget, GdkEventButton *event)
1440 {
1441   KryWaveform *waveform;
1442 
1443   g_return_val_if_fail (widget != NULL, FALSE);
1444   g_return_val_if_fail (KRY_IS_WAVEFORM (widget), FALSE);
1445   g_return_val_if_fail (event != NULL, FALSE);
1446 
1447   waveform = KRY_WAVEFORM (widget);
1448 
1449   if(waveform->button_press == FALSE)
1450     return FALSE;
1451 
1452   waveform->button_press = FALSE;
1453 
1454   if(!waveform->data_info)
1455     return FALSE;
1456 
1457   if(waveform->is_scrub_bar_dragging)
1458     waveform->is_scrub_bar_dragging = FALSE;
1459 
1460   if(waveform->marker_dragging)
1461   {
1462     waveform->marker_dragging = NULL;
1463     waveform->drag_select = FALSE;
1464 
1465     return FALSE;
1466   }
1467 
1468   if(event->button != 2)
1469     return FALSE;
1470 
1471   struct pavl_traverser iter;
1472   kry_region_fixed_list_get_iter(waveform->region_fixed_list, &iter);
1473   while(struct KryRegionFixedInfo *info = (struct KryRegionFixedInfo *) pavl_t_next(&iter))
1474   {
1475     for(GList *ptr = info->regions; ptr; ptr = ptr->next)
1476     {
1477       KryRegion *region = (KryRegion *) ptr->data;
1478 
1479       int mili = kry_waveform_mili_from_rel_pixel(waveform, (int) event->x);
1480       int start_mili = kry_marker_get_value(kry_region_get_marker_start(region));
1481       int end_mili = kry_marker_get_value(kry_region_get_marker_end(region));
1482 
1483       if(mili >= start_mili && mili <= end_mili)
1484       {
1485         kry_region_selected(region);
1486         break;
1487       }
1488     }
1489   }
1490 
1491   return FALSE;
1492 }
1493 
kry_waveform_setup_rel_keyframe_list(KryWaveform * waveform)1494 void kry_waveform_setup_rel_keyframe_list(KryWaveform *waveform)
1495 {
1496   waveform->keyframes_rel = NULL;
1497   waveform->keyframes_rel_count = 0;
1498 
1499   if(!waveform->keyframe_list || !waveform->data_info)
1500     return;
1501 
1502   long left_mili = (long) (((double) waveform->left / waveform->data_info->vals_per_sec) * 1000);
1503   for(int i = 0; i < waveform->keyframe_list->count; i++)
1504   {
1505     if(waveform->keyframe_list->list[i] >= left_mili)
1506     {
1507       waveform->keyframes_rel = waveform->keyframe_list->list + i;
1508       waveform->keyframes_rel_count = waveform->keyframe_list->count - i;
1509       break;
1510     }
1511   }
1512 }
1513 
kry_waveform_get_keyframe_list(KryWaveform * waveform)1514 struct KryWaveformKeyframeList *kry_waveform_get_keyframe_list(KryWaveform *waveform)
1515 {
1516   g_return_val_if_fail (waveform != NULL, NULL);
1517   g_return_val_if_fail (KRY_IS_WAVEFORM (waveform), NULL);
1518 
1519   return waveform->keyframe_list;
1520 }
1521 
kry_waveform_set_keyframe_list(KryWaveform * waveform,KryWaveformKeyframeList * list)1522 void kry_waveform_set_keyframe_list(KryWaveform *waveform, KryWaveformKeyframeList *list)
1523 {
1524   g_return_if_fail (waveform != NULL);
1525   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
1526 
1527   waveform->keyframe_list = list;
1528 
1529   kry_waveform_setup_rel_keyframe_list(waveform);
1530 
1531   kry_waveform_redraw(waveform);
1532 }
1533 
kry_waveform_get_zoom_internal(KryWaveform * waveform)1534 double kry_waveform_get_zoom_internal(KryWaveform *waveform)
1535 {
1536   double data_per_pixel = (waveform->data_info->vals_per_sec * waveform->zoom) / GTK_WIDGET(waveform)->allocation.width;
1537 
1538   return data_per_pixel;
1539 }
1540 
kry_waveform_data_process_range(KryWaveform * waveform,int sec_start,int sec_end)1541 void kry_waveform_data_process_range(KryWaveform *waveform, int sec_start, int sec_end)
1542 {
1543   int j;
1544   unsigned char *wave = (unsigned char *) waveform->data_info->waveform_data;
1545 
1546   int num_data = (int) waveform->data_per_pixel;
1547   if(waveform->data_per_pixel - (int) waveform->data_per_pixel > 0.01)
1548     num_data++;
1549 
1550   int pixel_start = kry_waveform_abs_pixel_from_mili(waveform, sec_start * 1000);
1551   int pixel_end = kry_waveform_abs_pixel_from_mili(waveform, sec_end * 1000);
1552 
1553 
1554   //g_warning("px %d - %d", pixel_start, pixel_end);
1555 
1556   int max_index = waveform->data_info->vals_per_sec * waveform->data_info->length_seconds * 2;
1557   int last_index = 0;
1558   for(int pixel = pixel_start; pixel < pixel_end; pixel++)
1559   {
1560     unsigned char vpos = 0, vneg = 0;
1561     int index = kry_waveform_get_index_at_abs_pixel(waveform, pixel);
1562 
1563     /*if(pixel > 0 && waveform->data_per_pixel - (int) waveform->data_per_pixel > 0.01)
1564     {
1565       int prev_end_index = kry_waveform_get_index_at_rel_pixel(waveform, pixel - 1) + (num_data - 1) * 2;
1566       if(index != prev_end_index)
1567       {
1568         num_data += (index - prev_end_index) / 2;
1569         index = prev_end_index;
1570       }
1571     }*/
1572 
1573     if(index + num_data * 2 >= max_index)
1574     {
1575       vpos = 0;
1576       vneg = 0;
1577 
1578       //int length_mili = waveform->data_info->length_seconds * 1000;
1579       //int pixels = kry_waveform_abs_pixel_from_mili(waveform, length_mili);
1580       //memset(waveform->data_per_pixel
1581     }
1582     else
1583     {
1584       // we find the maximum positive value of the points that represent the current pixel
1585       for(j = 0; j < num_data; j++)
1586         if(wave[index + j*2] > vpos)
1587           vpos = wave[index + j*2];
1588 
1589       // we find the maximum negative value of the points that represent the current pixel
1590       for(j = 0; j < num_data; j++)
1591         if(wave[index + j*2 + 1] > vneg)
1592           vneg = wave[index + j*2 + 1];
1593     }
1594 
1595     int px = pixel * 2;
1596     if(px + 1 < waveform->data_pixel_length)
1597     {
1598       waveform->data_pixel[px] = vpos;
1599       waveform->data_pixel[px + 1] = vneg;
1600     }
1601     last_index = px;
1602   }
1603 
1604   //g_warning("last index: %d", last_index);
1605 
1606   for(int i = sec_start; i < sec_end; i++)
1607     waveform->data_time[i] = 1;
1608 }
1609 
kry_waveform_data_thread(KryWaveform * waveform)1610 void kry_waveform_data_thread(KryWaveform *waveform)
1611 {
1612   g_mutex_lock(waveform->data_thread_mutex_global);
1613   for(int i = 0; i < waveform->data_info->length_seconds; i++)
1614   {
1615     g_mutex_lock(waveform->data_thread_mutex);
1616     if(waveform->data_time[i])
1617     {
1618       g_mutex_unlock(waveform->data_thread_mutex);
1619       continue;
1620     }
1621 
1622     if(waveform->data_thread_quit)
1623     {
1624       g_mutex_unlock(waveform->data_thread_mutex);
1625       break;
1626     }
1627 
1628     kry_waveform_data_process_range(waveform, i, i + 1);
1629 
1630     g_mutex_unlock(waveform->data_thread_mutex);
1631   }
1632 
1633   g_mutex_lock(waveform->data_thread_mutex);
1634   waveform->data_thread = NULL;
1635   g_mutex_unlock(waveform->data_thread_mutex);
1636   g_mutex_unlock(waveform->data_thread_mutex_global);
1637 }
1638 
kry_waveform_data_ensure_available(KryWaveform * waveform,int sec_start,int sec_end)1639 void kry_waveform_data_ensure_available(KryWaveform *waveform, int sec_start, int sec_end)
1640 {
1641   g_mutex_lock(waveform->data_thread_mutex);
1642   if(sec_start >= waveform->data_info->length_seconds)
1643     return;
1644 
1645   for(int i = sec_start; i < sec_end; i++)
1646   {
1647     if(waveform->data_time[i])
1648       continue;
1649 
1650     kry_waveform_data_process_range(waveform, i, i + 1);
1651   }
1652   g_mutex_unlock(waveform->data_thread_mutex);
1653 }
1654 
kry_waveform_data_thread_end(KryWaveform * waveform)1655 void kry_waveform_data_thread_end(KryWaveform *waveform)
1656 {
1657   g_mutex_lock(waveform->data_thread_mutex);
1658   if(waveform->data_thread)
1659   {
1660     waveform->data_thread_quit = TRUE;
1661     g_mutex_unlock(waveform->data_thread_mutex);
1662 
1663     g_mutex_lock(waveform->data_thread_mutex_global);
1664     g_mutex_unlock(waveform->data_thread_mutex_global);
1665 
1666     waveform->data_thread_quit = FALSE;
1667   }
1668   else
1669   {
1670     g_mutex_unlock(waveform->data_thread_mutex);
1671   }
1672 }
1673 
kry_waveform_update_zoom(KryWaveform * waveform)1674 void kry_waveform_update_zoom(KryWaveform *waveform)
1675 {
1676   if(!waveform->data_info)
1677     return;
1678 
1679   kry_waveform_data_thread_end(waveform);
1680 
1681   if(waveform->data_pixel)
1682     kry_free(waveform->data_pixel);
1683 
1684   if(waveform->data_time)
1685     kry_free(waveform->data_time);
1686 
1687   waveform->data_per_pixel = kry_waveform_get_zoom_internal(waveform);
1688 
1689   if(waveform->data_per_pixel < 1)
1690     waveform->data_per_pixel = 1;
1691 
1692   int length_mili = waveform->data_info->length_seconds * 1000;
1693   int pixels = kry_waveform_abs_pixel_from_mili(waveform, length_mili);
1694 
1695   //g_warning("allocated: %d", pixels * 2);
1696 
1697   waveform->data_pixel = kry_new(char, pixels * 2);
1698   waveform->data_pixel_length = pixels * 2;
1699   waveform->data_time = kry_new0_n(char, waveform->data_info->length_seconds);
1700   waveform->data_thread = g_thread_create((GThreadFunc) kry_waveform_data_thread, waveform, TRUE, NULL);
1701 
1702   if(waveform->adjustment)
1703   {
1704     kry_waveform_update_adjustment(waveform);
1705     if(waveform->adjustment->value > waveform->adjustment->upper - waveform->adjustment->page_size)
1706     {
1707       waveform->adjustment->value = waveform->adjustment->upper - waveform->adjustment->page_size;
1708       if(waveform->adjustment->value < 0)
1709         waveform->adjustment->value = 0;
1710 
1711 
1712       g_signal_emit_by_name(G_OBJECT(waveform->adjustment), "value-changed");
1713     }
1714   }
1715 }
1716 
kry_waveform_set_zoom(KryWaveform * waveform,double factor)1717 void kry_waveform_set_zoom(KryWaveform *waveform, double factor)
1718 {
1719   g_return_if_fail (waveform != NULL);
1720   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
1721 
1722   if(fabs(factor - kry_waveform_get_zoom(waveform)) < 0.0001)
1723     return;
1724 
1725   waveform->zoom = factor;
1726 
1727   g_signal_emit (waveform, kry_waveform_signals[ZOOM_CHANGED_SIGNAL], 0, factor);
1728 
1729   kry_waveform_update_zoom(waveform);
1730   kry_waveform_redraw(waveform);
1731 }
1732 
kry_waveform_get_zoom_min(KryWaveform * waveform)1733 double kry_waveform_get_zoom_min(KryWaveform *waveform)
1734 {
1735   g_return_val_if_fail (waveform != NULL, 1);
1736   g_return_val_if_fail (KRY_IS_WAVEFORM (waveform), 1);
1737 
1738   if(!waveform->data_info)
1739     return 1;
1740 
1741   double width = GTK_WIDGET(waveform)->allocation.width;
1742   return (width / waveform->data_info->vals_per_sec);
1743 }
1744 
kry_waveform_get_zoom_max(KryWaveform * waveform)1745 double kry_waveform_get_zoom_max(KryWaveform *waveform)
1746 {
1747   g_return_val_if_fail (waveform != NULL, 1);
1748   g_return_val_if_fail (KRY_IS_WAVEFORM (waveform), 1);
1749 
1750   if(!waveform->data_info)
1751     return 1;
1752 
1753   return waveform->data_info->length_seconds;
1754 }
1755 
kry_waveform_get_zoom(KryWaveform * waveform)1756 double kry_waveform_get_zoom(KryWaveform *waveform)
1757 {
1758   g_return_val_if_fail (waveform != NULL, 1);
1759   g_return_val_if_fail (KRY_IS_WAVEFORM (waveform), 1);
1760 
1761   if(!waveform->data_info)
1762     return 1;
1763 
1764   return waveform->zoom;
1765 }
1766 
kry_waveform_focus_selected(KryWaveform * waveform)1767 void kry_waveform_focus_selected(KryWaveform *waveform)
1768 {
1769   double selection_length = 0, window_length = 0;
1770   long start = 0, end = 0;
1771   long start_val = 0;
1772   long end_val = 0;
1773 
1774   g_return_if_fail (waveform != NULL);
1775   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
1776 
1777   if(!waveform->data_info)
1778     return;
1779 
1780   KryMarker *marker_start = waveform->marker_active_start;
1781   KryMarker *marker_end = waveform->marker_active_end;
1782 
1783   if(marker_start)
1784     start_val = kry_marker_get_value(marker_start);
1785 
1786   if(marker_end)
1787     end_val = kry_marker_get_value(marker_end);
1788 
1789   if(!marker_start || !marker_end
1790     || (start_val == -1 && end_val == -1))
1791       return;
1792 
1793   if(start_val != -1)
1794     start = (long) ((kry_marker_get_value(marker_start) / 1000.0) * waveform->data_info->vals_per_sec);
1795 
1796   if(end_val != -1)
1797     end = (long) ((kry_marker_get_value(marker_end) / 1000.0) * waveform->data_info->vals_per_sec);
1798 
1799   if(start_val != -1 && end_val != -1)
1800   {
1801     selection_length = ((double) end - start) / waveform->data_info->vals_per_sec;
1802     window_length = (double) (GTK_WIDGET(waveform)->allocation.width * waveform->data_per_pixel) / (waveform->data_info->vals_per_sec);
1803   }
1804   // can the selected region fit in weveform?
1805   if(selection_length < window_length && start_val != -1 && end_val != -1)
1806   {
1807     double left = (GTK_WIDGET(waveform)->allocation.width - ((end - start) / (double) waveform->data_per_pixel)) / 2.0;
1808     if(left < 250)
1809       left = 250;
1810 
1811     left *= waveform->data_per_pixel;
1812     waveform->adjustment->value = start - left;
1813 
1814   }
1815   else
1816   {
1817     if(start_val == -1)
1818       waveform->adjustment->value = end - (250 * waveform->data_per_pixel);
1819     else
1820       waveform->adjustment->value = start - (250 * waveform->data_per_pixel);
1821   }
1822 
1823   if(waveform->adjustment->value < 0)
1824       waveform->adjustment->value = 0;
1825 
1826   if(waveform->adjustment->value > waveform->adjustment->upper - waveform->adjustment->page_size)
1827     waveform->adjustment->value = waveform->adjustment->upper - waveform->adjustment->page_size;
1828 
1829   g_signal_emit_by_name(G_OBJECT(waveform->adjustment), "value-changed");
1830 }
1831 
1832 
1833 /*struct sound_info *kry_waveform_get_sound_info(KryWaveform *widget)
1834 {
1835   KryWaveform *waveform;
1836 
1837   g_return_val_if_fail (widget != NULL, FALSE);
1838   g_return_val_if_fail (KRY_IS_WAVEFORM (widget), FALSE);
1839 
1840   waveform = KRY_WAVEFORM (widget);
1841 
1842   return waveform->data_info;
1843 }*/
1844 
1845 /*void kry_waveform_set_data(KryWaveform *waveform, struct sound_info *sound_info)
1846 {
1847   g_return_if_fail (waveform != NULL);
1848   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
1849 
1850   waveform->sound_info = sound_info;
1851 }*/
1852 
1853 /*void kry_waveform_set_channel(KryWaveform *waveform, int channel)
1854 {
1855   g_return_if_fail (waveform != NULL);
1856   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
1857 
1858   waveform->channel = channel;
1859 }*/
1860 
kry_waveform_get_scale(KryWaveform * waveform)1861 double kry_waveform_get_scale(KryWaveform *waveform)
1862 {
1863   g_return_val_if_fail (waveform != NULL, 1);
1864   g_return_val_if_fail (KRY_IS_WAVEFORM (waveform), 1);
1865 
1866   return waveform->scale;
1867 }
1868 
kry_waveform_set_scale(KryWaveform * waveform,int value)1869 void kry_waveform_set_scale(KryWaveform *waveform, int value)
1870 {
1871   g_return_if_fail (waveform != NULL);
1872   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
1873 
1874   double scale_val = value / 100.0;
1875   if(fabs(scale_val - waveform->scale) < 0.0001)
1876     return;
1877 
1878   waveform->scale = scale_val;
1879 
1880   g_signal_emit (waveform, kry_waveform_signals[SCALE_CHANGED_SIGNAL], 0, value);
1881 
1882   kry_waveform_redraw(waveform);
1883 }
1884 
kry_waveform_find_first_region(KryWaveform * waveform,gboolean backward)1885 static void kry_waveform_find_first_region(KryWaveform *waveform, gboolean backward)
1886 {
1887   int counter = 0;
1888   gboolean found = FALSE;
1889   while(!found)
1890   {
1891 
1892     struct KryRegionFixedInfo *info = (struct KryRegionFixedInfo *) pavl_t_cur(&waveform->region_fixed_list_iter);
1893     if(!info)
1894       break;
1895 
1896     for(GList *ptr_h = info->regions; ptr_h; ptr_h = ptr_h->next)
1897     {
1898       struct KryRegionFixed *region = (struct KryRegionFixed *) ptr_h->data;
1899       long m1val = region->start;
1900       long m2val = region->end;
1901       long m1pos = kry_waveform_rel_pixel_from_mili(waveform, m1val);
1902       long m2pos = kry_waveform_rel_pixel_from_mili(waveform, m2val);
1903 
1904       counter++;
1905 
1906       if(m1val == -1 || m2val == -1 || m1val >= m2val)
1907         continue;
1908 
1909       gboolean region_match = (m1pos < 0 && m2pos > 0 || m1pos >= 0);
1910       if(!backward && region_match)
1911       {
1912         found = TRUE;
1913         break;
1914       }
1915       else if(backward && !region_match)
1916       {
1917         struct pavl_traverser iter = waveform->region_fixed_list_iter;
1918 
1919         pavl_t_next(&waveform->region_fixed_list_iter);
1920         if(!waveform->region_fixed_list_iter.pavl_node)
1921           waveform->region_fixed_list_iter = iter;
1922 
1923         found = TRUE;
1924         break;
1925       }
1926     }
1927 
1928     if(!found)
1929     {
1930       struct pavl_traverser iter = waveform->region_fixed_list_iter;
1931       if(!backward)
1932       {
1933         pavl_t_next(&waveform->region_fixed_list_iter);
1934       }
1935       else
1936       {
1937         pavl_t_prev(&waveform->region_fixed_list_iter);
1938       }
1939 
1940       if(pavl_t_cur(&waveform->region_fixed_list_iter) == NULL)
1941       {
1942         waveform->region_fixed_list_iter = iter;
1943         found = TRUE;
1944       }
1945     }
1946   }
1947 }
1948 
kry_waveform_adjustment_value_changed(GtkAdjustment * adjustment,gpointer data)1949 static void kry_waveform_adjustment_value_changed (GtkAdjustment *adjustment, gpointer data)
1950 {
1951   KryWaveform *waveform;
1952 
1953   g_return_if_fail (adjustment != NULL);
1954   g_return_if_fail (data != NULL);
1955 
1956   waveform = KRY_WAVEFORM (data);
1957 
1958   waveform->left = (long) adjustment->value;
1959 
1960   kry_waveform_setup_rel_keyframe_list(waveform);
1961   if(waveform->left != waveform->left_previous)
1962   {
1963     int curx = kry_waveform_abs_pixel_from_rel(waveform, 0);
1964     GdkRectangle *rect = &waveform->last_draw_rect;
1965 
1966     kry_waveform_find_first_region(waveform, curx < rect->x);
1967 
1968     // scroll to the right (image scrolls left)
1969     if(curx > rect->x && curx < rect->x + rect->width)
1970     {
1971       #ifdef _WINDOWS
1972       RECT scroll, clip;
1973       scroll.left = curx - rect->x;
1974       scroll.right = rect->width;
1975       scroll.top = waveform->scrub_bar_height + waveform->time_bar_height;
1976       scroll.bottom = waveform->wave_height + scroll.top;
1977 
1978       clip.left = 0;
1979       clip.right = rect->width;
1980       clip.top = scroll.top;
1981       clip.bottom = scroll.bottom;
1982 
1983       if(!ScrollDC(waveform->backbuffer_final, rect->x - curx, 0, &scroll, &clip, NULL, NULL))
1984         g_warning("scroll failed");
1985       #else
1986         gdk_draw_drawable(waveform->backbuffer_final, waveform->gc, waveform->backbuffer_final,
1987           curx - rect->x, waveform->time_bar_height + waveform->scrub_bar_height, 0,
1988           waveform->time_bar_height + waveform->scrub_bar_height, rect->width - (curx - rect->x), waveform->wave_height);
1989       #endif
1990 
1991       kry_waveform_redraw_partial(waveform, rect->width - (curx - rect->x), curx - rect->x, TRUE, FALSE);
1992       kry_waveform_update_front_buffer(waveform, 0, GTK_WIDGET(waveform)->allocation.width);
1993 
1994       rect->x = curx;
1995     }
1996     // scroll left (image moves right)
1997     else if(curx < rect->x && curx + rect->width > rect->x)
1998     {
1999       #ifdef _WINDOWS
2000       RECT scroll, clip;
2001       scroll.left = 0;
2002       scroll.right = rect->width - (rect->x - curx);
2003       scroll.top = waveform->scrub_bar_height + waveform->time_bar_height;
2004       scroll.bottom = waveform->wave_height + scroll.top;
2005 
2006       clip.left = 0;
2007       clip.right = rect->width;
2008       clip.top = scroll.top;
2009       clip.bottom = scroll.bottom;
2010 
2011       if(!ScrollDC(waveform->backbuffer_final, rect->x - curx, 0, &scroll, &clip, NULL, NULL))
2012         g_warning("scroll failed");
2013       #else
2014           gdk_draw_drawable(waveform->backbuffer_final, waveform->gc, waveform->backbuffer_final,
2015             0, waveform->time_bar_height + waveform->scrub_bar_height, rect->x - curx,
2016             waveform->time_bar_height + waveform->scrub_bar_height, rect->width - (rect->x - curx), waveform->wave_height);
2017       #endif
2018 
2019       kry_waveform_redraw_partial(waveform, 0, rect->x - curx, TRUE, FALSE);
2020       kry_waveform_update_front_buffer(waveform, 0, GTK_WIDGET(waveform)->allocation.width);
2021 
2022       rect->x = curx;
2023     }
2024     else
2025     {
2026       kry_waveform_redraw(waveform);
2027     }
2028 
2029     waveform->left_previous = waveform->left;
2030   }
2031 }
2032 
kry_waveform_marker_set_active_start(KryWaveform * waveform,KryMarker * marker)2033 void kry_waveform_marker_set_active_start(KryWaveform *waveform, KryMarker *marker)
2034 {
2035   g_return_if_fail (waveform != NULL);
2036   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
2037 
2038 
2039   KryMarker *old_marker = waveform->marker_active_start;
2040   waveform->marker_active_start = marker;
2041 
2042   if(!GTK_WIDGET_REALIZED(waveform))
2043     return;
2044 
2045   if(old_marker)
2046     kry_waveform_marker_redraw_at_time(waveform, kry_marker_get_value(old_marker));
2047 
2048   if(marker)
2049     kry_waveform_marker_redraw_at_time(waveform, kry_marker_get_value(marker));
2050 }
2051 
kry_waveform_marker_set_active_end(KryWaveform * waveform,KryMarker * marker)2052 void kry_waveform_marker_set_active_end(KryWaveform *waveform, KryMarker *marker)
2053 {
2054   g_return_if_fail (waveform != NULL);
2055   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
2056 
2057   KryMarker *old_marker = waveform->marker_active_end;
2058   waveform->marker_active_end = marker;
2059 
2060   if(!GTK_WIDGET_REALIZED(waveform))
2061     return;
2062 
2063   if(old_marker)
2064     kry_waveform_marker_redraw_at_time(waveform, kry_marker_get_value(old_marker));
2065 
2066   if(marker)
2067     kry_waveform_marker_redraw_at_time(waveform, kry_marker_get_value(marker));
2068 }
2069 
kry_waveform_get_color_table(KryWaveform * waveform)2070 kryColorTable *kry_waveform_get_color_table(KryWaveform *waveform)
2071 {
2072   g_return_val_if_fail (waveform != NULL, NULL);
2073   g_return_val_if_fail (KRY_IS_WAVEFORM (waveform), NULL);
2074 
2075   return waveform->color_table;
2076 }
2077 
kry_waveform_set_drag_selection(KryWaveform * waveform,gboolean drag)2078 void kry_waveform_set_drag_selection(KryWaveform *waveform, gboolean drag)
2079 {
2080   g_return_if_fail (waveform != NULL);
2081   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
2082 
2083   waveform->drag_selection_enabled = drag;
2084 }
2085 
kry_waveform_set_marker_dragging(KryWaveform * waveform,gboolean drag)2086 void kry_waveform_set_marker_dragging(KryWaveform *waveform, gboolean drag)
2087 {
2088   g_return_if_fail (waveform != NULL);
2089   g_return_if_fail (KRY_IS_WAVEFORM (waveform));
2090 
2091   waveform->drag_markers_enabled = drag;
2092 }
2093