Rewrote MidiRingBuffer to more efficiently pack data (flat pack stamps, sizes, and...
[ardour.git] / gtk2_ardour / marker_time_axis_view.cc
1 /*
2     Copyright (C) 2003 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <algorithm>
21
22 #include <gtkmm.h>
23 #include <gtkmm2ext/gtk_ui.h>
24
25 #include "marker_time_axis_view.h"
26 #include "marker_time_axis.h"
27 #include "marker_view.h"
28 #include "imageframe_view.h"
29 #include "imageframe_time_axis.h"
30 #include "canvas-simplerect.h"
31 #include "public_editor.h"
32 #include "rgb_macros.h"
33 #include "gui_thread.h"
34
35 #include "i18n.h"
36
37 using namespace ARDOUR ;
38 using namespace Editing;
39
40 //---------------------------------------------------------------------------------------//
41 // Constructor / Desctructor
42                 
43 /**
44  * Construct a new MarkerTimeAxisView helper time axis helper
45  *
46  * @param mta the TimeAxsiView that this objbect is the helper for
47  */
48 MarkerTimeAxisView::MarkerTimeAxisView(MarkerTimeAxis& tv)
49         : _trackview (tv)
50 {
51         region_color = _trackview.color();
52         stream_base_color = color_map[cMarkerTrackBase];
53
54         canvas_group = new ArdourCanvas::Group (*_trackview.canvas_display);
55
56         canvas_rect =  new ArdourCanvas::SimpleRect (*canvas_group);
57         canvas_rect->property_x1() = 0.0;
58         canvas_rect->property_y1() = 0.0;
59         canvas_rect->property_x2() = max_frames;
60         canvas_rect->property_y2() = (double)20;
61         canvas_rect->property_outline_color_rgba() = color_map[cMarkerTrackOutline];
62         canvas_rect->property_fill_color_rgba() = stream_base_color;
63                    
64         canvas_rect->signal_event().connect (bind (mem_fun (_trackview.editor, &PublicEditor::canvas_marker_time_axis_view_event), canvas_rect, &_trackview));
65
66         _samples_per_unit = _trackview.editor.get_current_zoom() ;
67
68         _trackview.editor.ZoomChanged.connect (mem_fun(*this, &MarkerTimeAxisView::reset_samples_per_unit));
69 }
70
71 /**
72  * Destructor
73  * Reposinsibly for destroying all marker items that may have been added to this time axis view
74  *
75  */
76 MarkerTimeAxisView::~MarkerTimeAxisView()
77 {
78         // destroy everything upon this view
79         for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter)
80         {
81                 MarkerView* mv = (*iter) ;
82                 
83                 MarkerViewList::iterator next = iter ;
84                 next++ ;
85                 marker_view_list.erase(iter) ;
86
87                 delete mv ;
88                 mv = 0 ;
89                 
90                 iter = next ;
91         }
92         
93         if(canvas_rect)
94         {
95                 delete canvas_rect;
96                 canvas_rect = 0 ;
97         }
98         
99         if(canvas_group)
100         {
101                 delete canvas_group;
102                 canvas_group = 0 ;
103         }
104 }
105
106
107 //---------------------------------------------------------------------------------------//
108 // ui methods & data
109
110 /**
111  * Sets the height of the time axis view and the item upon it
112  *
113  * @param height the new height
114  */
115 int
116 MarkerTimeAxisView::set_height(gdouble h)
117 {
118         if (h < 10.0 || h > 1000.0) {
119                 return -1;
120         }
121         
122         canvas_rect->property_y2() = h;
123
124         for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i) {
125                 (*i)->set_y_position_and_height(0, h);
126         }
127
128         return 0;
129 }
130
131 /**
132  * Sets the position of this view helper on the canvas
133  *
134  * @param x the x position upon the canvas
135  * @param y the y position upon the canvas
136  */
137 int
138 MarkerTimeAxisView::set_position(gdouble x, gdouble y)
139 {
140         canvas_group->property_x() = x;
141         canvas_group->property_y() = y;
142         return 0;
143 }
144
145 /**
146  * Sets the current samples per unit.
147  * this method tells each item upon the time axis of the change
148  * 
149  * @param spu the new samples per canvas unit value
150  */
151 int
152 MarkerTimeAxisView::set_samples_per_unit(gdouble spp)
153 {
154         if(spp < 1.0) {
155                 return -1 ;
156         }
157         
158         _samples_per_unit = spp ;
159
160         for(MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i)
161         {
162                 (*i)->set_samples_per_unit(spp) ;
163         }
164         return(0) ;
165 }
166
167 /**
168  * Sets the color of the items contained upon this view helper
169  *
170  * @param color the new base color
171  */
172 void
173 MarkerTimeAxisView::apply_color(Gdk::Color& color)
174 {
175         region_color = color;
176
177         for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); i++)
178         {
179                 (*i)->set_color (region_color) ;
180         }
181 }
182
183
184 //---------------------------------------------------------------------------------------//
185 // Child MarkerView Accessors/Mutators
186                 
187 /**
188  * Adds a marker view to the list of items upon this time axis view helper
189  * the new MarkerView is returned
190  *
191  * @param ifv the ImageFrameView that the new item is marking up
192  * @param mark_text the text to be displayed uopn the new marker item
193  * @param mark_id the unique id of the new item
194  * @param start the position the new item should be placed upon the time line
195  * @param duration the duration the new item should be placed upon the timeline
196  * @param src the identity of the object that initiated the change
197  */      
198 MarkerView*
199 MarkerTimeAxisView::add_marker_view(ImageFrameView* ifv, std::string mark_type, std::string mark_id, nframes_t start, nframes_t dur, void* src)
200 {
201         if(ifv->has_marker_view_item(mark_id))
202         {
203                 return(0) ;
204         }
205         
206         MarkerView* mv = new MarkerView(canvas_group,
207                  &_trackview,
208                  ifv,
209                  _trackview.editor.get_current_zoom(),
210                  region_color,
211                  mark_type,
212                  mark_id,
213                  start,
214                  dur) ;
215         
216         ifv->add_marker_view_item(mv, src) ;
217         marker_view_list.push_front(mv) ;
218         
219         mv->GoingAway.connect(bind (mem_fun(*this,&MarkerTimeAxisView::remove_marker_view), (void*)this)) ;
220         
221          MarkerViewAdded(mv,src) ; /* EMIT_SIGNAL */
222         
223         return(mv) ;
224 }
225
226 /**
227  * Returns the named MarkerView or 0 if the named marker does not exist
228  *
229  * @param item_id the unique id of the item to search for
230  * @return the named MarkerView, or 0 if it is not held upon this view
231  */
232 MarkerView*
233 MarkerTimeAxisView::get_named_marker_view(std::string item_id)
234 {
235         MarkerView* mv =  0 ;
236         
237         for(MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i)
238         {
239                 if(((MarkerView*)*i)->get_item_name() == item_id)
240                 {
241                         mv = ((MarkerView*)*i) ;
242                         break ;
243                 }
244         }
245         return(mv) ;
246 }
247
248 /**
249  * Removes the currently selected MarverView
250  * Note that this method actually destroys the MarkerView too.
251  * We assume that since we own the object, we are allowed to do this
252  *
253  * @param src the identity of the object that initiated the change
254  * @see add_marker_view
255  */
256 void
257 MarkerTimeAxisView::remove_selected_marker_view(void* src)
258 {
259         std::string removed ;
260         
261         if (selected_time_axis_item)
262         {
263                 MarkerViewList::iterator i ;
264                 if((i = find (marker_view_list.begin(), marker_view_list.end(), selected_time_axis_item)) != marker_view_list.end())
265                 {
266                         marker_view_list.erase(i) ;
267                         
268                          MarkerViewRemoved(selected_time_axis_item->get_item_name(),src) ; /* EMIT_SIGNAL */
269
270                         delete(selected_time_axis_item) ;
271                         selected_time_axis_item = 0 ;
272                 }
273         }
274         else
275         {
276                 //No selected marker view
277         }
278 }
279
280 /**
281  * Removes and returns the named MarkerView from the list of MarkerView held by this view helper
282  *
283  * @param item_id the MarkerView unique id to remove
284  * @param src the identity of the object that initiated the change
285  * @see add_marker_view
286  */
287 MarkerView*
288 MarkerTimeAxisView::remove_named_marker_view(std::string item_id, void* src)
289 {
290         MarkerView* mv = 0 ;
291         
292         MarkerViewList::iterator i = marker_view_list.begin() ;
293         
294         for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter)
295         {
296                 if(((MarkerView*)*i)->get_item_name() == item_id)
297                 {
298                         mv = ((MarkerView*)*i) ;
299                         marker_view_list.erase(i) ;
300                                                 
301                          MarkerViewRemoved(mv->get_item_name(), src) ; /* EMIT_SIGNAL */
302                         
303                         // break from the for loop
304                         break;
305                 }
306                 i++ ;
307         }
308         
309         return(mv) ;
310 }
311
312 /**
313  * Removes mv from the list of MarkerView upon this TimeAxis
314  *
315  * @param mv the MarkerView to remove
316  * @param src the identity of the object that initiated the change
317  */
318 void
319 MarkerTimeAxisView::remove_marker_view(MarkerView* mv, void* src)
320 {
321         ENSURE_GUI_THREAD(bind (mem_fun(*this, &MarkerTimeAxisView::remove_marker_view), mv, src));
322         
323         MarkerViewList::iterator i;
324
325         if((i = find (marker_view_list.begin(), marker_view_list.end(), mv)) != marker_view_list.end()) {
326                 marker_view_list.erase(i) ;
327                 
328                 // Assume this remove happened locally, else use remove_named_marker_time_axis
329                 // let listeners know that the named MarkerTimeAxis has been removed
330                  MarkerViewRemoved(mv->get_item_name(), src) ; /* EMIT_SIGNAL */
331         }
332 }
333
334
335 /**
336  * Sets the duration of the selected MarkerView to the specified number of seconds
337  *
338  * @param sec the duration to set the MArkerView to, in seconds
339  */
340 void
341 MarkerTimeAxisView::set_marker_duration_sec(double sec)
342 {
343   if(get_selected_time_axis_item() != 0)
344   {
345           get_selected_time_axis_item()->set_duration((nframes_t) (sec * _trackview.editor.current_session()->frame_rate()), this) ;
346   }
347 }
348
349
350 //---------------------------------------------------------------------------------------//
351 // Selected item methods
352
353 /**
354  * Sets the currently selected item upon this time axis
355  *
356  * @param mv the item to set selected
357  */
358 void
359 MarkerTimeAxisView::set_selected_time_axis_item(MarkerView* mv)
360 {
361         selected_time_axis_item = mv ;
362 }
363
364 /**
365  * Clears any selected item upon this time axis
366  *
367  */
368 void
369 MarkerTimeAxisView::clear_selected_time_axis_item()
370 {
371         selected_time_axis_item = 0 ;
372 }
373                 
374 /**
375  * Returnsthe currently selected item upon this time axis
376  *
377  * @return the currently selected item pon this time axis
378  */
379 MarkerView*
380 MarkerTimeAxisView::get_selected_time_axis_item()
381 {
382         return(selected_time_axis_item) ;
383 }
384
385
386
387
388 /**
389  * convenience method to re-get the samples per unit and tell items upon this view
390  *
391  */
392 void
393 MarkerTimeAxisView::reset_samples_per_unit ()
394 {
395         set_samples_per_unit(_trackview.editor.get_current_zoom()) ;
396 }