make that status-bar error change actually compile
[ardour.git] / gtk2_ardour / imageframe_socket_handler.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 <iostream>
21 #include <iomanip>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <unistd.h>
26 #include <arpa/inet.h>
27 #include <cstdio>
28
29 #include <sigc++/bind.h>
30
31 #include <gtkmm2ext/gtk_ui.h>
32
33 #include "imageframe_socket_handler.h"
34 #include "imageframe_time_axis.h"
35 #include "imageframe_time_axis_view.h"
36 #include "imageframe_time_axis_group.h"
37 #include "imageframe_view.h"
38 #include "marker_time_axis.h"
39 #include "marker_time_axis_view.h"
40 #include "ardour_ui.h"
41 #include "public_editor.h"
42 #include "gui_thread.h"
43
44 #include "i18n.h"
45
46 #include <ardour/session.h>
47
48 #include <unistd.h>
49
50 using namespace std;
51 using namespace ardourvis ;
52 using namespace sigc;
53 using namespace ARDOUR;
54 using namespace PBD;
55
56 ImageFrameSocketHandler* ImageFrameSocketHandler::_instance = 0 ;
57
58 /**
59  * Constructs a new ImageFrameSocketHandler to handle communication between Ardour and the Image Compositor
60  *
61  * @param ed the PublicEditor
62  */
63 ImageFrameSocketHandler::ImageFrameSocketHandler(PublicEditor& ed) : thePublicEditor(ed), theArdourToCompositorSocket(-1)
64 {
65         
66 }
67
68 /**
69  * Descructor
70  * this will shutdown the socket if open
71  */
72 ImageFrameSocketHandler::~ImageFrameSocketHandler()
73 {
74         close_connection() ;
75 }
76
77
78 /**
79  * Returns the instance of the ImageFrameSocketHandler
80  * the instance should first be created with createInstance
81  *
82  * @return the instance of the ImageFrameSocketHandler
83  */
84 ImageFrameSocketHandler* 
85 ImageFrameSocketHandler::get_instance()
86 {
87         return(_instance) ;
88 }
89
90 /**
91  * Create an new instance of the ImageFrameSocketHandler, if one does not already exist
92  *
93  * @param ed the Ardour PublicEditor
94  */
95 ImageFrameSocketHandler*
96 ImageFrameSocketHandler::create_instance(PublicEditor& ed)
97 {
98         if(_instance)
99         {
100                 return(_instance) ;
101         }
102         else
103         {
104                 _instance = new ImageFrameSocketHandler(ed) ;
105                 return(_instance) ;
106         }
107 }
108
109 /**
110  * call back to handle doing the processing work
111  * This method is added to the gdk main loop and called when there is data
112  * upon the socket.
113  *
114  */
115 void
116 ImageFrameSocketHandler::image_socket_callback(void *arg, int32_t fd, GdkInputCondition cond)
117 {
118         char buf[ardourvis::MAX_MSG_SIZE + 1] ;
119         memset(buf, 0, (ardourvis::MAX_MSG_SIZE + 1)) ;
120         buf[ardourvis::MAX_MSG_SIZE] = '\0' ;
121
122         int retcode = ::recv(fd, buf, MAX_MSG_SIZE, 0) ;
123         if (retcode == 0)
124         {
125                 //end-of-file, other end closed or shutdown?
126                 ARDOUR_UI::instance()->popup_error(_("Image Compositor Socket has been shutdown/closed"));
127                 
128                 // assume socket has been shutdown, tell, someone interested,
129                 // and remove the socket from the event loop
130                 ImageFrameSocketHandler* ifsh = ImageFrameSocketHandler::get_instance() ;
131                 gdk_input_remove(ifsh->theGdkInputTag) ;
132                 ifsh->close_connection() ;
133                  ifsh->CompositorSocketShutdown() ; /* EMIT_SIGNAL */
134         }
135         if(retcode > 0)
136         {
137                 //std::cout << "Received Msg [" << buf << "]\n" ;
138                 ImageFrameSocketHandler* ifsh = ImageFrameSocketHandler::get_instance() ;
139                 
140                 std::string mType = ifsh->get_message_part(0,2,buf) ;
141
142                 if(mType == ardourvis::INSERT_ITEM)
143                 {
144                         ifsh->handle_insert_message(buf) ;
145                 }
146                 else if (mType == ardourvis::REMOVE_ITEM)
147                 {
148                         ifsh->handle_remove_message(buf) ;
149                 }
150                 else if (mType == ardourvis::RENAME_ITEM)
151                 {
152                         ifsh->handle_rename_message(buf) ;
153                 }
154                 else if (mType == ardourvis::ITEM_UPDATE)
155                 {
156                         ifsh->handle_item_update_message(buf) ;
157                 }
158                 else if (mType == ardourvis::REQUEST_DATA)
159                 {
160                         ifsh->handle_request_data(buf) ;
161                 }
162                 else if (mType == ardourvis::ITEM_SELECTED)
163                 {
164                         ifsh->handle_item_selected(buf) ;
165                 }
166                 else if(mType == ardourvis::SESSION_ACTION)
167                 {
168                         ifsh->handle_session_action(buf) ;
169                 }
170                 else
171                 {
172                         std::string errMsg = "Unknown Message type : " ; 
173                         errMsg.append(mType) ;
174                         ifsh->send_return_failure(errMsg) ;
175                 }       
176         }
177 }
178
179 /**
180  * Attempt to connect to the image compositor on the specified host and port
181  *
182  * @param hostIp the ip address of the image compositor host
183  * @param port the oprt number to attemp the connection on
184  * @return true if the connection was a succees
185  *         false otherwise
186  */
187 bool
188 ImageFrameSocketHandler::connect(const char * hostIp, int32_t port)
189 {
190         if (is_connected())
191         {
192                 //already connected...
193                 return(true) ;
194         }
195         
196         theArdourToCompositorSocket = socket(AF_INET, SOCK_STREAM, 0) ;
197         if(theArdourToCompositorSocket == -1)
198         {
199                 return(false) ;
200         }
201         
202         int on = 1 ;
203         setsockopt(theArdourToCompositorSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) ;
204         
205         sockaddr_in m_addr ;
206         m_addr.sin_family = AF_INET ;
207         m_addr.sin_port = htons(port) ;
208         m_addr.sin_addr.s_addr = inet_addr(hostIp) ;
209         
210         int status = ::connect(theArdourToCompositorSocket, (sockaddr *) &m_addr, sizeof(m_addr)) ;
211         
212         if(status == -1)
213         {
214                 theArdourToCompositorSocket = -1 ;      
215                 return(false) ;
216         }
217         
218         return(true) ;
219 }
220
221 /**
222  * Closes the connection to th Image Compositor
223  *
224  */
225  void
226  ImageFrameSocketHandler::close_connection()
227  {
228         if(is_connected())
229         {
230                 ::close(theArdourToCompositorSocket) ;
231                 theArdourToCompositorSocket = -1 ;
232         }
233  }
234
235 /**
236  * Returns true if this ImagFrameSocketHandler is currently connected to rthe image compositor
237  *
238  * @return true if connected to the image compositor
239  */
240 bool
241 ImageFrameSocketHandler::is_connected()
242 {
243         return(theArdourToCompositorSocket == -1 ? false : true) ;
244 }
245
246 /**
247  * Sets the tag used to describe this input within gtk
248  * this is returned when gdk_input_add is called and is required to remove the input
249  *
250  * @param tag the gdk input tag of this input
251  */
252 void
253 ImageFrameSocketHandler::set_gdk_input_tag(int tag)
254 {
255         theGdkInputTag = tag ;
256 }
257
258 /**
259  * Returns the gdk input tag of this input
260  *
261  * @return the gdk input tag of this input
262  * @see setGdkInputTag
263  */
264 int
265 ImageFrameSocketHandler::get_gdk_input_tag()
266 {
267         return(theGdkInputTag) ;
268 }
269
270 /**
271  * Returns the socket file descriptor
272  *
273  * @return the Sockt file descriptor
274  */
275 int
276 ImageFrameSocketHandler::get_socket_descriptor()
277 {
278         return(theArdourToCompositorSocket) ;
279 }
280
281
282
283
284 //---------------------------------------------------------------------------------------//
285 // Handle Sending messages to the Image Compositor
286                 
287 //----------------------------
288 // ImageFrameTimeAxis Messages
289
290 /**
291  * Sends a message stating that the named image frame time axis has been removed
292  *
293  * @param track_id the unique id of the removed image frame time axis
294  * @param src the identity of the object that initiated the change
295  */
296 void
297 ImageFrameSocketHandler::send_imageframe_time_axis_removed(const string & track_id, void* src)
298 {
299         if(this == src || src == 0)
300         {
301                 // ie the change originated from us, then dont send any message back
302                 return ;
303         }
304         
305         // create a message buffer
306         std::ostringstream msgBuffer ;
307         msgBuffer << std::setfill('0') ;
308         
309         // add the msg type
310         msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::IMAGEFRAME_TIME_AXIS ;
311         
312         // add the id length, and the id
313         msgBuffer << std::setw(3) << track_id.length() ;
314         msgBuffer << track_id ;
315         
316         send_message(msgBuffer.str()) ;
317
318         // XXX should do something with the return
319         read_result();
320 }
321                 
322 /**
323  * Sends a message indicating that an ImageFrameTimeAxis has been renamed
324  *
325  * @param new_id the new name, or Id, of the track
326  * @param old_id the old name, or Id, of the track
327  * @param src the identity of the object that initiated the change
328  * @param time_axis the time axis that has changed
329  */
330 void
331 ImageFrameSocketHandler::send_imageframe_time_axis_renamed(const string & new_id, const string & old_id, void* src, ImageFrameTimeAxis* time_axis)
332 {
333         // ENSURE_GUI_THREAD(SigC::bind (mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_renamed), new_id, old_id, src, time_axis));
334         
335         if(this == src || src == 0)
336         {
337                 // ie the change originated from us, then dont send any message back
338                 return ;
339         }
340         
341         // create a message buffer
342         std::ostringstream msgBuffer ;
343         msgBuffer << std::setfill('0') ;
344         
345         // add the msg type
346         msgBuffer << ardourvis::RENAME_ITEM << ardourvis::IMAGEFRAME_TIME_AXIS ;
347         
348         // add the old id and length
349         msgBuffer << std::setw(3) << old_id.length() ;
350         msgBuffer << old_id ;
351         
352         // add the new id and length
353         msgBuffer << std::setw(3) << new_id.length() ;
354         msgBuffer << new_id ;
355         
356         send_message(msgBuffer.str()) ;
357
358         // XXX should do something with the return
359         read_result();
360 }
361
362 //------------------------
363 // MarkerTimeAxis Messages
364                 
365 /**
366  * Sends a message stating that the named marker time axis has been removed
367  *
368  * @param track_id the unique id of the removed image frame time axis
369  * @param src the identity of the object that initiated the change
370  */
371 void
372 ImageFrameSocketHandler::send_marker_time_axis_removed(const string & track_id, void* src)
373 {
374         if(this == src || src == 0)
375         {
376                 // ie the change originated from us, then dont send any message back
377                 return ;
378         }
379         
380         // create a message buffer
381         std::ostringstream msgBuffer ;
382         msgBuffer << std::setfill('0') ;
383         
384         // add the msg type
385         msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::MARKER_TIME_AXIS ;
386         
387         // add the id length, and the id
388         msgBuffer << std::setw(3) << track_id.length() ;
389         msgBuffer << track_id ;
390         
391         send_message(msgBuffer.str()) ;
392
393         // XXX should do something with the return
394         read_result();
395 }
396                 
397 /**
398  * Sends a message indicating that an MarkerTimeAxis has been renamed
399  *
400  * @param new_id the new name, or Id, of the track
401  * @param old_id the old name, or Id, of the track
402  * @param src the identity of the object that initiated the change
403  * @param time_axis the time axis that has changed
404  */
405 void
406 ImageFrameSocketHandler::send_marker_time_axis_renamed(const string & new_id, const string & old_id, void* src, MarkerTimeAxis* time_axis)
407 {
408         // ENSURE_GUI_THREAD(bind (mem_fun(*this, &ImageFrameSocketHandler::send_marker_time_axis_renamed), new_id, old_id, src, time_axis));
409         
410         if(this == src || src == 0)
411         {
412                 // ie the change originated from us, then dont send any message back
413                 return ;
414         }
415         
416         // ctreate a message buffer
417         std::ostringstream msgBuffer ;
418         msgBuffer << std::setfill('0') ;
419         
420         // add the msg type
421         msgBuffer << ardourvis::RENAME_ITEM << ardourvis::MARKER_TIME_AXIS ;
422         
423         // add the old id and length
424         msgBuffer << std::setw(3) << old_id.length() ;
425         msgBuffer << old_id ;
426         
427         // add the new id and length
428         msgBuffer << std::setw(3) << new_id.length() ;
429         msgBuffer << new_id ;
430         
431         send_message(msgBuffer.str()) ;
432         
433         // XXX should do something with the return
434         read_result();
435 }
436
437 //---------------------------------
438 // ImageFrameTimeAxisGroup Messages
439
440 /**
441  * Sends a message stating that the group has been removed
442  *
443  * @param group_id the unique id of the removed image frame time axis
444  * @param src the identity of the object that initiated the change
445  * @param group the group that has changed
446  */
447 void
448 ImageFrameSocketHandler::send_imageframe_time_axis_group_removed(const string & group_id, void* src, ImageFrameTimeAxisGroup* group)
449 {
450         if(this == src || src == 0)
451         {
452                 // ie the change originated from us, then dont send any message back
453                 return ;
454         }
455         
456         // create a message buffer
457         std::ostringstream msgBuffer ;
458         msgBuffer << std::setfill('0') ;
459         
460         // add the msg type
461         msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::IMAGEFRAME_GROUP ;
462         
463         // add the id length, and the id of the parent image time axis
464         std::string track_id = group->get_view().trackview().name() ;
465         msgBuffer << std::setw(3) << track_id.length() ;
466         msgBuffer << track_id ;
467         
468         // add the group id and length
469         msgBuffer << std::setw(3) << group_id.length() ;
470         msgBuffer << group_id ;
471         
472         send_message(msgBuffer.str()) ;
473
474         // XXX should do something with the return
475         read_result();
476 }
477
478 /**
479  * Send a message indicating that an ImageFrameTimeAxisGroup has been renamed
480  *
481  * @param new_id the new name, or Id, of the group
482  * @param old_id the old name, or Id, of the group
483  * @param src the identity of the object that initiated the change
484  * @param group the group that has changed
485  */
486 void
487 ImageFrameSocketHandler::send_imageframe_time_axis_group_renamed(const string & new_id, const string & old_id, void* src, ImageFrameTimeAxisGroup* group)
488 {
489         // ENSURE_GUI_THREAD(bind (mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_group_renamed), new_id, old_id, src, group));
490         
491         if(this == src || src == 0)
492         {
493                 // ie the change originated from us, then dont send any message back
494                 return ;
495         }
496         
497         // ctreate a message buffer
498         std::ostringstream msgBuffer ;
499         msgBuffer << std::setfill('0') ;
500         
501         // add the msg type
502         msgBuffer << ardourvis::RENAME_ITEM << ardourvis::IMAGEFRAME_GROUP ;
503         
504         // add the track this group is upon
505         std::string track_id = group->get_view().trackview().name() ;
506         msgBuffer << std::setw(3) << track_id.length() << track_id ; 
507         
508         // add the old id and length
509         msgBuffer << std::setw(3) << old_id.length() ;
510         msgBuffer << old_id ;
511         
512         // add the new id and length
513         msgBuffer << std::setw(3) << new_id.length() ;
514         msgBuffer << new_id ;
515         
516         send_message(msgBuffer.str()) ;
517         
518         // XXX should do something with the return
519         read_result();
520 }
521
522
523 //---------------------------------
524 // ImageFrameView Messages
525                 
526 /**
527  * Send an Image Frame View Item position changed message
528  *
529  * @param pos the new position value
530  * @param src the identity of the object that initiated the change
531  * @param item the time axis item whos position has changed
532  */
533 void
534 ImageFrameSocketHandler::send_imageframe_view_position_change(nframes_t pos, void* src, ImageFrameView* item)
535 {
536         // ENSURE_GUI_THREAD(bind (mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_view_position_change), pos, src, item));
537         
538         if(this == src || src == 0)
539         {
540                 return ;
541         }
542         
543         // create a message buffer
544         std::ostringstream msgBuffer ;
545         msgBuffer << std::setfill('0') ;
546         
547         // add the msg type
548         msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::IMAGEFRAME_ITEM << ardourvis::POSITION_CHANGE ;
549         
550         // add the item description
551         this->compose_imageframe_item_desc(item, msgBuffer) ;
552
553         msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << pos ;
554         
555         send_message(msgBuffer.str()) ;
556         
557         // XXX should do something with the return
558         read_result();
559 }
560                 
561 /**
562  * Send a Image Frame View item duration changed message
563  *
564  * @param dur the the new duration value
565  * @param src the identity of the object that initiated the change
566  * @param item the item which has had a duration change
567  */
568 void
569 ImageFrameSocketHandler::send_imageframe_view_duration_change(nframes_t dur, void* src, ImageFrameView* item)
570 {
571         // ENSURE_GUI_THREAD(bind (mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_view_duration_change), dur, src, item));
572         
573         if(this == src || src == 0)
574         {
575                 return ;
576         }
577         
578         // create a message buffer
579         std::ostringstream msgBuffer ;
580         msgBuffer << std::setfill('0') ;
581         
582         // add the msg type
583         msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::IMAGEFRAME_ITEM << ardourvis::DURATION_CHANGE ;
584         
585         this->compose_imageframe_item_desc(item, msgBuffer) ;
586
587         msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << dur ;
588         
589         send_message(msgBuffer.str()) ;
590         
591         // XXX should do something with the return
592         read_result();
593 }
594                 
595 /**
596  * Send a message indicating that an ImageFrameView has been renamed
597  *
598  * @param item the ImageFrameView which has been renamed
599  * @param src the identity of the object that initiated the change
600  * @param item the renamed item
601  */
602 void
603 ImageFrameSocketHandler::send_imageframe_view_renamed(const string & new_id, const string & old_id, void* src, ImageFrameView* item)
604 {
605         if(this == src || src == 0)
606         {
607                 // ie the change originated from us, then dont send any message back
608                 return ;
609         }
610         
611         // ctreate a message buffer
612         std::ostringstream msgBuffer ;
613         msgBuffer << std::setfill('0') ;
614         
615         // add the msg type
616         msgBuffer << ardourvis::RENAME_ITEM << ardourvis::IMAGEFRAME_ITEM ;
617         
618         this->compose_imageframe_item_desc(item, msgBuffer) ;
619         
620         // add the old id and length
621         msgBuffer << std::setw(3) << old_id.length() ;
622         msgBuffer << old_id ;
623         
624         send_message(msgBuffer.str()) ;
625         
626         // XXX should do something with the return
627         read_result();
628 }
629                 
630 /**
631  * Send a message indicating that an ImageFrameView item has been removed message
632  *
633  * @param item_id the id of the item that was removed
634  * @param item the removed item
635  */
636 void
637 ImageFrameSocketHandler::send_imageframe_view_removed(const string & item_id, void* src, ImageFrameView* item)
638 {
639         if(this == src || src == 0)
640         {
641                 // ie the change originated from us, then dont send any message back
642                 return ;
643         }
644         
645         // create a message buffer
646         std::ostringstream msgBuffer ;
647         msgBuffer << std::setfill('0') ;
648         
649         // add the msg type
650         msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::IMAGEFRAME_ITEM ;
651         
652         // add the id length, and the id
653         ImageFrameTimeAxisGroup* parentGroup = item->get_time_axis_group() ;
654         std::string group_id = parentGroup->get_group_name() ;
655         std::string track_id = parentGroup->get_view().trackview().name() ;
656         msgBuffer << std::setw(3) << track_id.length() << track_id ;
657         msgBuffer << std::setw(3) << group_id.length() << group_id ;
658         msgBuffer << std::setw(3) << item_id.length() << item_id ;
659         
660         send_message(msgBuffer.str()) ;
661
662         // XXX should do something with the return
663         read_result();
664 }
665
666
667
668
669 //---------------------------------
670 // MarkerView Messages
671                 
672 /**
673  * Send a Marker View Item position changed message
674  *
675  * @param pos the new position value
676  * @param src the identity of the object that initiated the change
677  * @param item the time axis item whos position has changed
678  */
679 void
680 ImageFrameSocketHandler::send_marker_view_position_change(nframes_t pos, void* src, MarkerView* item)
681 {
682         if(this == src || src == 0)
683         {
684                 return ;
685         }
686         
687         // create a message buffer
688         std::ostringstream msgBuffer ;
689         msgBuffer << std::setfill('0') ;
690         
691         // add the msg type
692         msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::MARKER_ITEM << ardourvis::POSITION_CHANGE ;
693         
694         // add the item description
695         this->compose_marker_item_desc(item, msgBuffer) ;
696
697         msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << pos ;
698         
699         send_message(msgBuffer.str()) ;
700
701         // XXX should do something with the return
702         read_result();
703 }
704                 
705 /**
706  * Send a Marker View item duration changed message
707  *
708  * @param dur the new duration value
709  * @param src the identity of the object that initiated the change
710  * @param item the time axis item whos position has changed
711  */
712 void
713 ImageFrameSocketHandler::send_marker_view_duration_change(nframes_t dur, void* src, MarkerView* item)
714 {
715         if(this == src || src == 0)
716         {
717                 return ;
718         }
719         
720         // create a message buffer
721         std::ostringstream msgBuffer ;
722         msgBuffer << std::setfill('0') ;
723         
724         // add the msg type
725         msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::MARKER_ITEM << ardourvis::DURATION_CHANGE ;
726         
727         this->compose_marker_item_desc(item, msgBuffer) ;
728
729         msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << dur ;
730         
731         send_message(msgBuffer.str()) ;
732
733         // XXX should do something with the return
734         read_result();
735 }       
736
737                 
738 /**
739  * Send a message indicating that a MarkerView has been renamed
740  *
741  * @param new_id the new_id of the object
742  * @param old_id the old_id of the object
743  * @param src the identity of the object that initiated the change
744  * @param item the MarkerView which has been renamed
745  */
746 void
747 ImageFrameSocketHandler::send_marker_view_renamed(const string & new_id, const string & old_id, void* src, MarkerView* item)
748 {
749         if(this == src || src == 0)
750         {
751                 // ie the change originated from us, then dont send any message back
752                 return ;
753         }
754         
755         // ctreate a message buffer
756         std::ostringstream msgBuffer ;
757         msgBuffer << std::setfill('0') ;
758         
759         // add the msg type
760         msgBuffer << ardourvis::RENAME_ITEM << ardourvis::MARKER_ITEM ;
761         
762         this->compose_marker_item_desc(item, msgBuffer) ;
763         
764         // add the old id and length
765         msgBuffer << std::setw(3) << old_id.length() ;
766         msgBuffer << old_id ;
767         
768         send_message(msgBuffer.str()) ;
769         
770         // XXX should do something with the return
771         read_result();
772 }
773                 
774 /**
775  * Send a message indicating that a MarkerView  item has been removed message
776  *
777  * @param item_id the id of the item that was removed
778  * @param src the identity of the object that initiated the change
779  * @param item the MarkerView which has been removed
780  */
781 void
782 ImageFrameSocketHandler::send_marker_view_removed(const string & item_id, void* src, MarkerView* item) 
783 {
784         if(this == src || src == 0)
785         {
786                 // ie the change originated from us, then dont send any message back
787                 return ;
788         }
789         
790         // create a message buffer
791         std::ostringstream msgBuffer ;
792         msgBuffer << std::setfill('0') ;
793         
794         // add the msg type
795         msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::MARKER_ITEM ;
796         
797         // add the id length, and the id
798         std::string track_id = item->get_time_axis_view().name() ;
799         msgBuffer << std::setw(3) << track_id.length() << track_id ;
800         msgBuffer << std::setw(3) << item_id.length() << item_id ;
801         
802         send_message(msgBuffer.str()) ;
803
804         // XXX should do something with the return
805         read_result();
806 }
807
808
809
810
811
812
813
814
815
816
817
818 //---------------------------------------------------------------------------------------//
819 //---------------------------------------------------------------------------------------//
820 //---------------------------------------------------------------------------------------//
821 // Message breakdown ie avoid a big if...then...else
822         
823
824 /**
825  * Handle insert item requests
826  *
827  * @param msg the received message
828  */
829 void
830 ImageFrameSocketHandler::handle_insert_message(const char* msg)
831 {
832         // handle the insert item message
833         // determine the object type to insert based upon characters 2-3
834         
835         std::string oType = get_message_part(2,2,msg) ;
836
837         if(oType == ardourvis::IMAGEFRAME_TIME_AXIS)
838         {
839                 this->handle_insert_imageframe_time_axis(msg) ;
840         }
841         else if (oType == ardourvis::MARKER_TIME_AXIS)
842         {
843                 this->handle_insert_marker_time_axis(msg) ;
844         }
845         else if (oType == ardourvis::IMAGEFRAME_GROUP)
846         {
847                 this->handle_insert_imageframe_group(msg) ;
848         }
849         else if (oType == ardourvis::IMAGEFRAME_ITEM)
850         {
851                 this->handle_insert_imageframe_view(msg) ;
852         }
853         else if (oType == ardourvis::MARKER_ITEM)
854         {
855                 this->handle_insert_marker_view(msg) ;
856         }
857         else
858         {
859                 std::string errMsg = "Unknown Object type during insert: " ; 
860                 errMsg.append(oType) ;
861                 send_return_failure(errMsg) ;
862         }
863 }
864
865 /**
866  * Handle remove item requests
867  *
868  * @param msg the received message
869  */
870 void
871 ImageFrameSocketHandler::handle_remove_message(const char* msg)
872 {
873         // handle the removal of an item message
874         // determine the object type to remove based upon characters 2-3
875         
876         std::string oType = get_message_part(2,2,msg) ;
877
878         if(oType == ardourvis::IMAGEFRAME_TIME_AXIS)
879         {
880                 this->handle_remove_imageframe_time_axis(msg) ;
881         }
882         else if (oType == ardourvis::MARKER_TIME_AXIS)
883         {
884                 this->handle_remove_marker_time_axis(msg) ;
885         }
886         else if (oType == ardourvis::IMAGEFRAME_ITEM)
887         {
888                 this->handle_remove_imageframe_view(msg) ;
889         }
890         else if (oType == ardourvis::MARKER_ITEM)
891         {
892                 this->handle_remove_marker_view(msg) ;
893         }
894         else
895         {
896                 std::string errMsg = "Unknown Object type during Remove: " ; 
897                 errMsg.append(oType) ;
898                 send_return_failure(errMsg) ;
899         }
900 }
901
902 /**
903  * Handle rename item requests
904  *
905  * @param msg the received message
906  */
907 void
908 ImageFrameSocketHandler::handle_rename_message(const char* msg)
909 {
910         // handle the renaming of an item message
911         // determine the object type to rename based upon characters 2-3
912         
913         std::string oType = get_message_part(2,2,msg) ;
914         
915         if(oType == ardourvis::IMAGEFRAME_TIME_AXIS)
916         {
917                 this->handle_rename_imageframe_time_axis(msg) ;
918         }
919         else if (oType == ardourvis::MARKER_TIME_AXIS)
920         {
921                 this->handle_rename_marker_time_axis(msg) ;
922         }
923         else if (oType == ardourvis::IMAGEFRAME_ITEM)
924         {
925                 this->handle_rename_imageframe_view(msg) ;
926         }
927         else if (oType == ardourvis::MARKER_ITEM)
928         {
929                 this->handle_rename_marker_view(msg) ;
930         }
931         else
932         {
933                 std::string errMsg = "Unknown Object type during Rename: " ; 
934                 errMsg.append(oType) ;
935                 send_return_failure(errMsg) ;
936         }
937 }
938
939 /**
940  * Handle a request for session information
941  *
942  * @param msg the received message
943  */
944 void
945 ImageFrameSocketHandler::handle_request_data(const char* msg)
946 {
947         // determine the request type
948         std::string reqType = get_message_part(2,2,msg) ;
949         
950         if(reqType == ardourvis::SESSION_NAME)
951         {
952                 handle_session_name_request(msg) ;
953         }
954 }
955
956 /**
957  * Handle the update of a particular item
958  *
959  * @param msg the received message
960  */
961 void 
962 ImageFrameSocketHandler::handle_item_update_message(const char* msg)
963 {
964         // determin the object that requires updating, characters 2-3
965         std::string oType = get_message_part(2,2,msg) ;
966         
967         // What needs updating? chars 4-5
968         std::string  attr = get_message_part(4,2,msg) ;
969         
970         if(oType == ardourvis::IMAGEFRAME_ITEM)
971         {
972                 if(attr == ardourvis::POSITION_CHANGE)
973                 {
974                         handle_imageframe_view_position_update(msg) ;
975                 }
976                 else if(attr == ardourvis::DURATION_CHANGE)
977                 {
978                         handle_imageframe_view_duration_update(msg) ;
979                 }
980                 else if(attr == ardourvis::POSITION_LOCK_CHANGE)
981                 {
982                         handle_imageframe_position_lock_update(msg) ;
983                 }
984                 else if(attr == ardourvis::MAX_DURATION_CHANGE)
985                 {
986                         handle_imageframe_view_max_duration_update(msg) ;
987                 }
988                 else if(attr == ardourvis::MAX_DURATION_ENABLE_CHANGE)
989                 {
990                         handle_imageframe_view_max_duration_enable_update(msg) ;
991                 }
992                 else if(attr == ardourvis::MIN_DURATION_CHANGE)
993                 {
994                         handle_imageframe_view_min_duration_update(msg) ;
995                 }
996                 else if(attr == ardourvis::MIN_DURATION_ENABLE_CHANGE)
997                 {
998                         handle_imageframe_view_min_duration_enable_update(msg) ;
999                 }
1000                 else
1001                 {
1002                         std::string errMsg = "Unknown Attribute during Item Update: " ; 
1003                         errMsg.append(oType) ;
1004                         send_return_failure(errMsg) ;
1005                 }
1006         }
1007         else if(oType == ardourvis::MARKER_ITEM)
1008         {
1009                 if(attr == ardourvis::POSITION_CHANGE)
1010                 {
1011                         handle_marker_view_position_update(msg) ;
1012                 }
1013                 else if(attr == ardourvis::DURATION_CHANGE)
1014                 {
1015                         handle_marker_view_duration_update(msg) ;
1016                 }
1017                 else
1018                 {
1019                         std::string errMsg = "Unknown Attribute during Item Update: " ; 
1020                         errMsg.append(oType) ;
1021                         send_return_failure(errMsg) ;
1022                 }
1023         }
1024         else
1025         {
1026                 std::string errMsg = "Unknown Object type during Item Update: " ; 
1027                 errMsg.append(oType) ;
1028                 send_return_failure(errMsg) ;
1029         }
1030 }
1031
1032 /**
1033  * Handle the selection of an Item
1034  *
1035  * @param msg the received message
1036  */
1037 void
1038 ImageFrameSocketHandler::handle_item_selected(const char* msg)
1039 {
1040         // determine the object that requires updating, characters 2-3
1041         std::string oType = get_message_part(2,2,msg) ;
1042         
1043         if(oType == std::string(ardourvis::IMAGEFRAME_ITEM))
1044         {
1045                 int position = 4 ; // message type chars
1046         
1047                 std::string track_id ;
1048                 std::string scene_id ;
1049                 std::string item_id ;
1050                 int track_id_size ;
1051                 int scene_id_size ;
1052                 int item_id_size ;
1053         
1054                 this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, scene_id, scene_id_size, item_id, item_id_size) ;
1055                 
1056                 // get the named time axis
1057                 ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_id)) ;
1058                 
1059                 if(!ifta)
1060                 {
1061                         send_return_failure(std::string("No parent Image Track found : ").append(track_id)) ;
1062                 }
1063                 else
1064                 {
1065                         // get the parent scene
1066                         ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_id) ;
1067                         if(!iftag)
1068                         {
1069                                 send_return_failure(std::string("No parent Scene found : ").append(scene_id)) ;
1070                         }
1071                         else
1072                         {
1073                                 ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ;
1074                                 if(!ifv)
1075                                 {
1076                                         send_return_failure(std::string("No Image Frame Item found : ").append(item_id)) ;
1077                                 }
1078                                 else
1079                                 {
1080                                         ifv->set_selected(true) ;
1081                                         ifta->get_view()->set_selected_imageframe_view(iftag, ifv) ;
1082
1083                                         thePublicEditor.scroll_timeaxis_to_imageframe_item(ifv) ;
1084                                         send_return_success() ;
1085                                 }
1086                         }
1087                 }
1088         }
1089 }
1090
1091 /**
1092  * Handle s session action message
1093  *
1094  * @param msg the received message
1095  */
1096 void
1097 ImageFrameSocketHandler::handle_session_action(const char* msg)
1098 {
1099         std::string actionType = get_message_part(2,2,msg) ;
1100         
1101         if(actionType == ardourvis::OPEN_SESSION)
1102         {
1103                 this->handle_open_session(msg) ;
1104         }
1105 }
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115 //---------------------------------------------------------------------------------------//
1116 // handlers for specific insert procedures
1117         
1118 /**
1119  * Handle the insertion of a new ImaegFrameTimeAxis
1120  *
1121  * @param msg the received message
1122  */
1123 void
1124 ImageFrameSocketHandler::handle_insert_imageframe_time_axis(const char* msg)
1125 {
1126         int position = 4 ; // message type chars
1127         
1128         // get the ImageFrameTrack name size
1129         int track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
1130         position += ardourvis::TEXT_SIZE_CHARS ;
1131         
1132         // get the image frame track name
1133         std::string track_name = get_message_part(position, track_name_size, msg) ;
1134         position += track_name_size ;
1135         
1136         // check we dont already have an time axis with that name
1137         TimeAxisView* tav = thePublicEditor.get_named_time_axis(track_name) ;
1138         if(tav)
1139         {
1140                 std::string errmsg("Track already exists: ") ;
1141                 errmsg.append(track_name) ;
1142                 send_return_failure(errmsg) ;
1143         }
1144         else
1145         {
1146                 thePublicEditor.add_imageframe_time_axis(track_name, this) ;
1147                 TimeAxisView* new_tav = thePublicEditor.get_named_time_axis(track_name) ;
1148         
1149                 if(new_tav)
1150                 {
1151                         ImageFrameTimeAxis* ifta = (ImageFrameTimeAxis*)new_tav ;
1152                         ifta->VisualTimeAxisRemoved.connect(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_removed)) ;
1153                         ifta->NameChanged.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_renamed), ifta)) ;
1154                         
1155                         send_return_success() ;
1156                 }
1157                 else
1158                 {
1159                         std::string msg("Addition Failed: ") ;
1160                         msg.append(track_name) ; 
1161                         send_return_failure(msg) ;
1162                 }
1163         }
1164 }
1165
1166
1167 /**
1168  * Handle the insertion of a new MarkerTimeAxis
1169  *
1170  * @param msg the received message
1171  */
1172 void
1173 ImageFrameSocketHandler::handle_insert_marker_time_axis(const char* msg)
1174 {
1175         int position = 4 ; // message type chars
1176         
1177         // get the ImageFrameTrack name size
1178         int track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
1179         position += ardourvis::TEXT_SIZE_CHARS ;
1180         
1181         // get the image frame track name
1182         std::string track_name = get_message_part(position, track_name_size, msg) ;
1183         position += track_name_size ;
1184         
1185         // get the size of the name of the associated track
1186         int assoc_track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
1187         position += ardourvis::TEXT_SIZE_CHARS ;
1188         
1189         // get the name of the track we associate the marker track with 
1190         std::string assoc_track_name = get_message_part(position, assoc_track_name_size, msg) ;
1191         position += assoc_track_name_size ;
1192
1193         // check that we dont already have a time axis with that name
1194         TimeAxisView* checkTav = thePublicEditor.get_named_time_axis(track_name) ;
1195         if(checkTav)
1196         {
1197                 std::string errmsg("Track already exists: ") ;
1198                 errmsg.append(track_name) ;
1199                 send_return_failure(errmsg) ;
1200         }
1201         else
1202         {
1203                 // check the associated time axis exists
1204                 TimeAxisView* assoc_tav = thePublicEditor.get_named_time_axis(assoc_track_name) ;
1205                 if(assoc_tav)
1206                 {
1207                         thePublicEditor.add_imageframe_marker_time_axis(track_name, assoc_tav, this) ;
1208                         TimeAxisView* new_tav = thePublicEditor.get_named_time_axis(track_name) ;
1209                         
1210                         bool added = false ;
1211                         
1212                         if(new_tav)
1213                         {
1214                                 MarkerTimeAxis* mta = dynamic_cast<MarkerTimeAxis*>(new_tav) ;
1215                                 if(mta)
1216                                 {
1217                                         added = true ;
1218                                         mta->VisualTimeAxisRemoved.connect(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_marker_time_axis_removed)) ;
1219                                         mta->NameChanged.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_marker_time_axis_renamed), mta)) ;
1220                                 }
1221                         }
1222                         
1223                         if(added)
1224                         {
1225                                 std::string msg("Addition Failed: ") ;
1226                                 msg.append(track_name) ; 
1227                                 send_return_failure(msg) ;
1228                         }
1229                 }
1230                 else
1231                 {
1232                         std::string errmsg("No associated Track Found: ") ;
1233                         errmsg.append(track_name) ;
1234                         send_return_failure(errmsg) ;
1235                 }
1236         }
1237 }
1238
1239 /**
1240  * Handle the insertion of a time axis group (a scene)
1241  *
1242  * @param msg the received message
1243  */
1244 void
1245 ImageFrameSocketHandler::handle_insert_imageframe_group(const char* msg)
1246 {
1247         int position = 4 ; // message type chars
1248         
1249         // get the ImageFrameTrack name size
1250         int track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
1251         position += ardourvis::TEXT_SIZE_CHARS ;
1252         
1253         // get the image frame track name
1254         std::string track_name = get_message_part(position, track_name_size, msg) ;
1255         position += track_name_size ;
1256         
1257         // get the scene id size
1258         int scene_id_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
1259         position += ardourvis::TEXT_SIZE_CHARS ;
1260         
1261         // get the scene id
1262         std::string scene_id = get_message_part(position, scene_id_size, msg) ;
1263         position += scene_id_size ;
1264         
1265         
1266         // get the named ImageFrameTrack
1267         ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_name)) ;
1268         
1269         // check we got a valid ImageFrameTimeAxis
1270         if(!ifta)
1271         {
1272                 send_return_failure(std::string("No Image Frame Time Axis Found: ").append(track_name)) ;
1273                 return ;
1274         }
1275         
1276         ImageFrameTimeAxisGroup* iftag = ifta->get_view()->add_imageframe_group(scene_id, this) ;
1277         if(!iftag)
1278         {
1279                 send_return_failure(std::string("Image Frame Group insert failed")) ;
1280         }
1281         else
1282         {
1283                 iftag->NameChanged.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_group_renamed), iftag)) ;
1284                 iftag->GroupRemoved.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_group_removed), iftag)) ;
1285                 send_return_success() ;
1286         }
1287 }
1288
1289
1290 /**
1291  * Handle the insertion of a new ImageFrameItem
1292  *
1293  * @param msg the received message
1294  */
1295 void
1296 ImageFrameSocketHandler::handle_insert_imageframe_view(const char* msg)
1297 {
1298         int position = 4 ; // message type chars
1299         
1300         // get the ImageFrameTrack name size
1301         int track_name_size = atoi(get_message_part(position,3,msg).c_str()) ;
1302         position += 3 ;
1303         
1304         // get the ImageFrameTrack Name
1305         std::string imageframe_track_name = get_message_part(position,track_name_size,msg) ;
1306         position += track_name_size ;
1307         
1308         // get the scene name size
1309         int scene_size = atoi(get_message_part(position,3,msg).c_str()) ;
1310         position += 3 ;
1311         
1312         // get the scene Name
1313         std::string scene_name = get_message_part(position,scene_size,msg) ;
1314         position += scene_size ;
1315         
1316         // get the image frame_id size
1317         int image_id_size = atoi(get_message_part(position,3,msg).c_str()) ;
1318         position += 3 ;
1319         
1320         // get the image frame_id
1321         std::string image_id = get_message_part(position,image_id_size,msg) ;
1322         position += image_id_size ;
1323         
1324         // get the start frame value
1325         nframes_t start = strtoul((get_message_part(position,10,msg).c_str()),0,10) ;
1326         position += 10 ;
1327         
1328         // get the duration value
1329         nframes_t duration = strtoul((get_message_part(position,10,msg).c_str()),0,10) ;
1330         position += 10 ;
1331
1332         //get the named time axis view we about to add an image to
1333         TimeAxisView* tav = thePublicEditor.get_named_time_axis(imageframe_track_name) ;
1334         ImageFrameTimeAxis* ifta = 0 ;
1335         
1336         if(tav)
1337         {
1338                 ifta = dynamic_cast<ImageFrameTimeAxis*>(tav) ;
1339         }
1340         
1341         if(!ifta)
1342         {
1343                 std::string errmsg("No Parent Image Track Found: ") ;
1344                 errmsg.append(imageframe_track_name) ;
1345                 send_return_failure(errmsg) ;
1346                 
1347                 // dont really like all these returns mid-way
1348                 // but this is goinf to get awfully if..then nested if not
1349                 return ;
1350         }
1351         
1352         // check the parent group exists
1353         ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_name) ;
1354         if(!iftag)
1355         {
1356                 std::string errmsg("No Image Frame Group Found: ") ;
1357                 errmsg.append(scene_name) ;
1358                 send_return_failure(errmsg) ;
1359                 return ;
1360         }
1361         
1362         // ok, so we have the parent group and track, now we need dome image data
1363         
1364         
1365         //
1366         // request the image data from the image compositor
1367         //
1368         
1369         // ctreate a message buffer
1370         std::ostringstream reqBuffer ;
1371         reqBuffer << std::setfill('0') ;
1372         
1373         // add the msg type
1374         reqBuffer << REQUEST_DATA << IMAGE_RGB_DATA ;
1375         
1376         // add the image track and size
1377         reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << track_name_size ;
1378         reqBuffer << imageframe_track_name ;
1379         
1380         // add the scene id and size
1381         reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << scene_size ;
1382         reqBuffer << scene_name ;
1383         
1384         // add the image id and size
1385         reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << image_id_size ;
1386         reqBuffer << image_id ;
1387         
1388         // add the preferred image height
1389         reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << ifta->get_image_display_height() ;
1390         
1391         // send the request message
1392         send_message(reqBuffer.str()) ;
1393
1394
1395         // read the reply, the inital image data message
1396         // this gives us the image dimensions and the expected size of the image data
1397         // msg type(4) + image width(3) + height(3) + num channels(3) + size of the image data (32)
1398         std::string init_image_data_msg ;
1399         read_message(init_image_data_msg) ;
1400         int init_msg_pos = 4 ;
1401         
1402         int imgWidth    = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_SIZE_CHARS).c_str()) ;
1403         init_msg_pos += ardourvis::IMAGE_SIZE_CHARS ;
1404         int imgHeight    = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_SIZE_CHARS).c_str()) ;
1405         init_msg_pos += ardourvis::IMAGE_SIZE_CHARS ;
1406         int imgChannels    = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_SIZE_CHARS).c_str()) ;
1407         init_msg_pos += ardourvis::IMAGE_SIZE_CHARS ; 
1408         int imgSize = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_DATA_MESSAGE_SIZE_CHARS).c_str()) ;
1409
1410         // send a success msg
1411         // we need to do this to keep things moving
1412         send_return_success() ;
1413
1414         // create our image rgb buffer, this holds the image data we receive
1415         unsigned char* rgb_img_buf = new unsigned char[imgSize] ;
1416
1417         int retcode = ::recv(theArdourToCompositorSocket, rgb_img_buf, imgSize, MSG_WAITALL) ;
1418
1419         if(retcode != imgSize)
1420         {
1421                 delete [] rgb_img_buf ;
1422                 send_return_failure("Could not create new Image Frame View : image data sizes did not match") ;
1423         }
1424         else
1425         {
1426                 ImageFrameView* ifv = iftag->add_imageframe_item(image_id, start, duration, rgb_img_buf, (uint32_t)imgWidth, (uint32_t)imgHeight, (uint32_t)imgChannels, this) ;
1427                 if(ifv)
1428                 {
1429                         ifv->PositionChanged.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_view_position_change), ifv)) ;
1430                         ifv->DurationChanged.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_view_duration_change), ifv)) ;
1431                         ifv->ItemRemoved.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_view_removed), ifv)) ;
1432                 
1433                         send_return_success() ;
1434                 }
1435                 else
1436                 {
1437                         //addition failed. assume duplicate item_id
1438                         send_return_failure("Could not create new Image Frame View") ;
1439                 }
1440         }
1441 }
1442
1443
1444
1445 /**
1446  * Handle the insertion of a new MarkerItem
1447  *
1448  * @param msg the received message
1449  */
1450 void
1451 ImageFrameSocketHandler::handle_insert_marker_view(const char* msg)
1452 {}
1453         
1454         
1455 //---------------------------------------------------------------------------------------//
1456 // handlers for specific removal procedures
1457
1458
1459 /**
1460  * Handle the removal of an ImageTimeAxis
1461  *
1462  * @param msg the received message
1463  */
1464 void
1465 ImageFrameSocketHandler::handle_remove_imageframe_time_axis(const char* msg)
1466 {}
1467                 
1468 /**
1469  * Handle the removal of an MarkerTimeAxis
1470  *
1471  * @param msg the received message
1472  */
1473 void
1474 ImageFrameSocketHandler::handle_remove_marker_time_axis(const char* msg)
1475 {}
1476                 
1477 /**
1478  * Handle the removal of an ImageFrameTimeAxisGroup
1479  *
1480  * @param msg the received message
1481  */
1482 void
1483 ImageFrameSocketHandler::handle_remove_imageframe_time_axis_group(const char* msg)
1484 {}
1485                 
1486 /**
1487  * Handle the removal of an ImageFrameItem
1488  *
1489  * @param msg the received message
1490  */
1491 void
1492 ImageFrameSocketHandler::handle_remove_imageframe_view(const char* msg)
1493 {}
1494                 
1495 /**
1496  * Handle the removal of an MarkerItem
1497  *
1498  * @param msg the received message
1499  */
1500 void
1501 ImageFrameSocketHandler::handle_remove_marker_view(const char* msg)
1502 {}
1503
1504
1505         
1506         
1507
1508 //---------------------------------------------------------------------------------------//
1509 // handlers for the specific rename procedures  
1510         
1511 /**
1512  * Handle the renaming of an ImageTimeAxis
1513  *
1514  * @param msg the received message
1515  */
1516 void
1517 ImageFrameSocketHandler::handle_rename_imageframe_time_axis(const char* msg)
1518 {
1519         // msg [MVIT][oldSize][oldId][newSize][newId]
1520         
1521         int position = 4 ; // message type chars
1522
1523         // get the old Id size
1524         int old_id_size = atoi(get_message_part(position,3,msg).c_str()) ;
1525         position += 3 ;
1526         
1527         // get the old id
1528         std::string old_id = get_message_part(position,old_id_size,msg) ;
1529         position += old_id_size ;
1530         
1531         //get the new Id size
1532         int new_id_size = atoi(get_message_part(position,3,msg).c_str()) ;
1533         position += 3 ;
1534         
1535         // get the new Id
1536         std::string new_id = get_message_part(position,new_id_size,msg) ;
1537         position += new_id_size ;
1538         
1539         // get the Named time axis
1540         TimeAxisView* tav = thePublicEditor.get_named_time_axis(old_id) ;
1541         if(dynamic_cast<ImageFrameTimeAxis*>(tav))
1542         {
1543                 ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(tav) ;
1544                 ifta->set_time_axis_name(new_id, this) ;
1545                 send_return_success() ;
1546         }
1547         else
1548         {
1549                 std::string msg = "No Image Track Found: " ;
1550                 msg.append(old_id) ;
1551                 send_return_failure(msg) ;
1552         }
1553 }
1554                 
1555 /**
1556  * Handle the renaming of an MarkerTimeAxis
1557  *
1558  * @param msg the received message
1559  */
1560 void
1561 ImageFrameSocketHandler::handle_rename_marker_time_axis(const char* msg)
1562 {}
1563                 
1564 /**
1565  * Handle the renaming of an ImageFrameItem
1566  *
1567  * @param msg the received message
1568  */
1569 void
1570 ImageFrameSocketHandler::handle_rename_imageframe_time_axis_group(const char* msg)
1571 {}
1572         
1573 /**
1574  * Handle the renaming of an ImageFrameItem
1575  *
1576  * @param msg the received message
1577  */
1578 void
1579 ImageFrameSocketHandler::handle_rename_imageframe_view(const char* msg)
1580 {}
1581                 
1582 /**
1583  * Handle the renaming of an Marker
1584  *
1585  * @param msg the received message
1586  */
1587 void
1588 ImageFrameSocketHandler::handle_rename_marker_view(const char* msg)
1589 {}
1590         
1591         
1592
1593         
1594 //---------------------------------------------------------------------------------------//
1595 // handlers for data request
1596         
1597 /**
1598  * Handle a request for the sessnio naem fo the current session
1599  * We return a failure state if no session is open
1600  *
1601  * @param msg the received message
1602  */
1603 void
1604 ImageFrameSocketHandler::handle_session_name_request(const char* msg)
1605 {
1606         ARDOUR::Session* currentSession = thePublicEditor.current_session() ;
1607         
1608         if(currentSession == 0)
1609         {
1610                 // no current session, return failure
1611                 std::string msg("No Current Session") ;
1612                 send_return_failure(msg) ;
1613         }
1614         else
1615         {
1616                 std::string sessionName = currentSession->name() ;
1617                 std::string sessionPath = currentSession->path() ;
1618                 
1619                 if(sessionPath[sessionPath.length() -1] != '/')
1620                 {
1621                         sessionPath.append("/") ;
1622                 }
1623                 
1624                 sessionPath.append(sessionName) ;
1625                 
1626                 std::ostringstream msgBuf ;
1627                 msgBuf << ardourvis::RETURN_DATA << ardourvis::SESSION_NAME ;
1628                 msgBuf << std::setfill('0') ;
1629                 msgBuf << std::setw(ardourvis::TEXT_SIZE_CHARS) << sessionPath.length() ;
1630                 msgBuf << sessionPath ;
1631                 send_message(msgBuf.str()) ;
1632         }
1633 }
1634         
1635         
1636
1637
1638
1639 //---------------------------------------------------------------------------------------//
1640 // handlers for specific item update changes
1641         
1642 /**
1643  * Handle ImageFrameView positional changes
1644  *
1645  * @param msg the received message
1646  */
1647 void
1648 ImageFrameSocketHandler::handle_imageframe_view_position_update(const char* msg)
1649 {
1650         int position = 6 ; // message type chars
1651         
1652         std::string track_id ;
1653         std::string scene_id ;
1654         std::string item_id ;
1655         int track_id_size ;
1656         int scene_id_size ;
1657         int item_id_size ;
1658         
1659         this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, scene_id, scene_id_size, item_id, item_id_size) ;
1660         
1661         nframes_t start_frame = strtoul(get_message_part(position, ardourvis::TIME_VALUE_CHARS, msg).c_str(), 0, 10) ;
1662         position += ardourvis::TIME_VALUE_CHARS ;
1663         
1664         // get the named time axis
1665         ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_id)) ;
1666         
1667         if(!ifta)
1668         {
1669                 send_return_failure(std::string("No parent Image Track found: ").append(track_id)) ;
1670                 return ;
1671         }
1672         
1673         // get the parent scene
1674         ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_id) ;
1675         if(!iftag)
1676         {
1677                 send_return_failure(std::string("No parent Scene found: ").append(scene_id)) ;
1678                 return ;
1679         }
1680         
1681         ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ;
1682         
1683         if(!ifv)
1684         {
1685                 send_return_failure(std::string("No Image Frame Item found: ").append(item_id)) ;
1686                 return ;
1687         }
1688         
1689
1690         ifv->set_position(start_frame, this) ;
1691         send_return_success() ;
1692 }
1693                 
1694 /**
1695  * Handle ImageFrameView Duration changes
1696  *
1697  * @param msg the received message
1698  */
1699 void
1700 ImageFrameSocketHandler::handle_imageframe_view_duration_update(const char* msg)
1701 {
1702         int position = 6 ; // message type chars
1703         
1704         std::string track_id ;
1705         std::string scene_id ;
1706         std::string item_id ;
1707         int track_id_size ;
1708         int scene_id_size ;
1709         int item_id_size ;
1710         
1711         this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, scene_id, scene_id_size, item_id, item_id_size) ;
1712         
1713         nframes_t duration = strtoul(get_message_part(position,ardourvis::TIME_VALUE_CHARS,msg).c_str(),0,10) ;
1714         position += ardourvis::TIME_VALUE_CHARS ;
1715         
1716         // get the named time axis
1717         ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_id)) ;
1718         
1719         if(!ifta)
1720         {
1721                 send_return_failure(std::string("No parent Image Track found : ").append(track_id)) ;
1722                 return ;
1723         }
1724         
1725         // get the parent scene
1726         ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_id) ;
1727         if(!iftag)
1728         {
1729                 send_return_failure(std::string("No parent Scene found : ").append(scene_id)) ;
1730                 return ;
1731         }
1732         
1733         ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ;
1734         
1735         if(!ifv)
1736         {
1737                 send_return_failure(std::string("No Image Frame Item found : ").append(item_id)) ;
1738                 return ;
1739         }
1740         
1741         ifv->set_duration(duration, this) ;
1742         send_return_success() ;
1743 }
1744
1745 /**
1746  * Handle ImageFrameView Position Lock Constraint changes
1747  *
1748  * @param msg the received message
1749  */
1750 void
1751 ImageFrameSocketHandler::handle_imageframe_position_lock_update(const char* msg)
1752 {
1753         int position = 6 ; // message type chars
1754         
1755         std::string track_id ;
1756         std::string group_id ;
1757         std::string item_id ;
1758         int track_id_size ;
1759         int group_id_size ;
1760         int item_id_size ;
1761         
1762         this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
1763         
1764         std::string pos_lock = get_message_part(position,1,msg) ;
1765         bool pos_lock_active = false ;
1766         
1767         if(pos_lock == "0")
1768         {
1769                 pos_lock_active = false ;
1770         }
1771         else if(pos_lock == "1")
1772         {
1773                 pos_lock_active = true ;
1774         }
1775         else
1776         {
1777                 send_return_failure(std::string("Unknown Value used during Position Loack: ").append(pos_lock)) ;
1778                 return ;
1779         }
1780         
1781         position += 1 ;
1782         
1783         int errcode ;
1784         std::string errmsg ;
1785         ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
1786         if(ifv)
1787         {
1788                 ifv->set_position_locked(pos_lock_active, this) ;
1789                 send_return_success() ;
1790         }
1791         else
1792         {
1793                 send_return_failure(errmsg) ;
1794         }
1795 }
1796                 
1797 /**
1798  * Handle ImageFrameView Maximum Duration changes
1799  *
1800  * @param msg the received message
1801  */
1802 void
1803 ImageFrameSocketHandler::handle_imageframe_view_max_duration_update(const char* msg)
1804 {
1805         int position = 6 ; // message type chars
1806         
1807         std::string track_id ;
1808         std::string group_id ;
1809         std::string item_id ;
1810         int track_id_size ;
1811         int group_id_size ;
1812         int item_id_size ;
1813         
1814         this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
1815         
1816         nframes_t max_duration = strtoul(get_message_part(position,ardourvis::TIME_VALUE_CHARS,msg).c_str(),0,10) ;
1817         position += ardourvis::TIME_VALUE_CHARS ;
1818         
1819         int errcode ;
1820         std::string errmsg ;
1821         ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
1822         if(ifv)
1823         {
1824                 ifv->set_max_duration(max_duration, this) ;
1825                 send_return_success() ;
1826         }
1827         else
1828         {
1829                 send_return_failure(errmsg) ;
1830         }
1831 }
1832         
1833 /**
1834  * Handle image frame max duration enable constraint changes
1835  *
1836  * @param msg the received message
1837  */
1838 void
1839 ImageFrameSocketHandler::handle_imageframe_view_max_duration_enable_update(const char* msg)
1840 {
1841         int position = 6 ; // message type chars
1842         
1843         std::string track_id ;
1844         std::string group_id ;
1845         std::string item_id ;
1846         int track_id_size ;
1847         int group_id_size ;
1848         int item_id_size ;
1849         
1850         this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
1851         
1852         std::string active = get_message_part(position,1,msg) ;
1853         bool max_duration_active = false ;
1854         
1855         if(active == "0")
1856         {
1857                 max_duration_active = false ;
1858         }
1859         else if(active == "1")
1860         {
1861                 max_duration_active = true ;
1862         }
1863         else
1864         {
1865                 send_return_failure(std::string("Unknown Value used during enable max duration: ").append(active)) ;
1866                 return ;
1867         }
1868         
1869         position += 1 ;
1870         
1871         int errcode ;
1872         std::string errmsg ;
1873         ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
1874         if(ifv)
1875         {
1876                 ifv->set_max_duration_active(max_duration_active, this) ;
1877                 send_return_success() ;
1878         }
1879         else
1880         {
1881                 send_return_failure(errmsg) ;
1882         }
1883 }
1884                 
1885 /**
1886  * Handle ImageFrameView Minimum Duration changes
1887  *
1888  * @param msg the received message
1889  */
1890 void
1891 ImageFrameSocketHandler::handle_imageframe_view_min_duration_update(const char* msg)
1892 {
1893         int position = 6 ; // message type chars
1894         
1895         std::string track_id ;
1896         std::string group_id ;
1897         std::string item_id ;
1898         int track_id_size ;
1899         int group_id_size ;
1900         int item_id_size ;
1901         
1902         this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
1903         
1904         nframes_t min_duration = strtoul(get_message_part(position,ardourvis::TIME_VALUE_CHARS,msg).c_str(),0,10) ;
1905         position += ardourvis::TIME_VALUE_CHARS ;
1906         
1907         int errcode ;
1908         std::string errmsg ;
1909         ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
1910         if(ifv)
1911         {
1912                 ifv->set_min_duration(min_duration, this) ;
1913                 send_return_success() ;
1914         }
1915         else
1916         {
1917                 send_return_failure(errmsg) ;
1918         }
1919 }
1920         
1921 /**
1922  * Handle image frame min duration enable constraint changes
1923  *
1924  * @param msg the received message
1925  */
1926 void
1927 ImageFrameSocketHandler::handle_imageframe_view_min_duration_enable_update(const char* msg)
1928 {
1929         int position = 6 ; // message type chars
1930         
1931         std::string track_id ;
1932         std::string group_id ;
1933         std::string item_id ;
1934         int track_id_size ;
1935         int group_id_size ;
1936         int item_id_size ;
1937         
1938         this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
1939         
1940         std::string active = get_message_part(position,1,msg) ;
1941         bool min_duration_active = false ;
1942         
1943         if(active == "0")
1944         {
1945                 min_duration_active = false ;
1946         }
1947         else if(active == "1")
1948         {
1949                 min_duration_active = true ;
1950         }
1951         else
1952         {
1953                 send_return_failure(std::string("Unknown Value used during enable max duration: ").append(active)) ;
1954                 return ;
1955         }
1956         
1957         position += 1 ;
1958         
1959         int errcode ;
1960         std::string errmsg ;
1961         ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
1962         if(ifv)
1963         {
1964                 ifv->set_min_duration_active(min_duration_active, this) ;
1965                 send_return_success() ;
1966         }
1967         else
1968         {
1969                 send_return_failure(errmsg) ;
1970         }
1971 }
1972         
1973 /**
1974  * Handle MarkerView position changes
1975  *
1976  * @param msg the received message
1977  */
1978 void
1979 ImageFrameSocketHandler::handle_marker_view_position_update(const char* msg)
1980 {}
1981                 
1982 /**
1983  * Handle MarkerView duration changes
1984  *
1985  * @param msg the received message
1986  */
1987 void
1988 ImageFrameSocketHandler::handle_marker_view_duration_update(const char* msg)
1989 {}
1990
1991 /**
1992  * Handle MarkerView Position Lock Constraint changes
1993  *
1994  * @param msg the received message
1995  */
1996 void
1997 ImageFrameSocketHandler::handle_marker_view_position_lock_update(const char* msg)
1998 {
1999 }
2000                 
2001 /**
2002  * Handle MarkerView maximum duration changes
2003  *
2004  * @param msg the received message
2005  */
2006 void
2007 ImageFrameSocketHandler::handle_marker_view_max_duration_update(const char* msg)
2008 {}
2009                 
2010 /**
2011  * Handle MarkerView minimum duration changes
2012  *
2013  * @param msg the received message
2014  */
2015 void
2016 ImageFrameSocketHandler::handle_marker_view_min_duration_update(const char* msg)
2017 {}
2018
2019
2020
2021
2022
2023 //---------------------------------------------------------------------------------------//
2024 // handlers for Session Actions
2025         
2026 /**
2027  * Handle the opening of a named audio session
2028  *
2029  * @param msg the received message
2030  */
2031 void
2032 ImageFrameSocketHandler::handle_open_session(const char* msg)
2033 {
2034         // msg [SAOS][sessionSize][sessionPath]
2035         
2036         int position = 4 ; // message type chars
2037
2038         // get the session name size
2039         int session_name_size = atoi(get_message_part(position,3,msg).c_str()) ;
2040         position += 3 ;
2041         
2042         // get the session name
2043         std::string session_name = get_message_part(position,session_name_size,msg) ;
2044         position += session_name_size ;
2045         
2046         
2047         // open the session     
2048         std::string path, name ;
2049         bool isnew;
2050
2051         if (ARDOUR::Session::find_session(session_name, path, name, isnew) == 0) {
2052                 if (ARDOUR_UI::instance()->load_session (path, name) == 0) {
2053                         send_return_success() ;
2054                 } else {
2055                         std::string retMsg = "Failed to load Session" ;
2056                         send_return_failure(retMsg) ;
2057                 }
2058         } else {
2059                 std::string retMsg = "Failed to find Session" ;
2060                 send_return_failure(retMsg) ;
2061         }
2062 }
2063
2064                 
2065 /**
2066  * Handle the closing of a named audio session
2067  *
2068  * @param msg the received message
2069  */
2070 void
2071 ImageFrameSocketHandler::handle_closed_session(const char* msg)
2072 {}
2073         
2074 //---------------------------------------------------------------------------------------//
2075 // handlers for the shutdown of the Image Compositor
2076                 
2077 /**
2078  * Handle the shutdown message from the image compositor
2079  *
2080  * @param msg the received message
2081  */
2082 void
2083 ImageFrameSocketHandler::handle_shutdown(const char* msg)
2084 {
2085          CompositorSocketShutdown() ; /* EMIT_SIGNAL */
2086 }
2087
2088
2089
2090
2091
2092
2093
2094
2095         
2096         
2097 //---------------------------------------------------------------------------------------//
2098 // convenince methods to break up messages
2099         
2100 /**
2101  * Returns part of the received message as a std::string
2102  *
2103  * @param start the start character
2104  * @param num_chars the number of characters to read
2105  * @param the message to break apart
2106  * @return the sub string of the message
2107                  */
2108 std::string
2109 ImageFrameSocketHandler::get_message_part(int start, int32_t num_chars, const char* msg)
2110 {
2111         char buf[num_chars + 1] ;
2112         strncpy(buf,msg+start,num_chars) ;
2113         buf[num_chars] = '\0' ;
2114         std::string s(buf) ;
2115         
2116         return(s) ;
2117 }
2118
2119
2120
2121 /**
2122  * break up am image item description message
2123  * we break the mesage up into the parent Image Track id and size,
2124  * the parent group id and size, and the image id and size
2125  *
2126  * @param track_id
2127  * @param track_id_size
2128  * @param scene_id
2129  * @param scene_id_size
2130  * @param item_id
2131  * @param item_id_size
2132  */
2133 void
2134 ImageFrameSocketHandler::decompose_imageframe_item_desc(const char* msg, int& position, std::string& track_id,
2135         int& track_id_size, std::string& scene_id, int& scene_id_size, std::string& item_id, int& item_id_size)
2136 {
2137         // get the track Id size
2138         track_id_size = atoi(get_message_part(position,ardourvis::TEXT_SIZE_CHARS,msg).c_str()) ;
2139         position += ardourvis::TEXT_SIZE_CHARS ;
2140         
2141         // get the track id
2142         track_id = get_message_part(position,track_id_size,msg) ;
2143         position += track_id_size ;
2144         
2145         // get the track Id size
2146         scene_id_size = atoi(get_message_part(position,ardourvis::TEXT_SIZE_CHARS,msg).c_str()) ;
2147         position += ardourvis::TEXT_SIZE_CHARS ;
2148         
2149         // get the scene id
2150         scene_id = get_message_part(position,scene_id_size,msg) ;
2151         position += scene_id_size ;
2152         
2153         // get the item id size
2154         item_id_size = atoi(get_message_part(position,ardourvis::TEXT_SIZE_CHARS,msg).c_str()) ;
2155         position += ardourvis::TEXT_SIZE_CHARS ;
2156         
2157         // get the item id
2158         item_id = get_message_part(position,item_id_size,msg) ;
2159         position += item_id_size ;
2160 }
2161
2162 /**
2163  * Compose a description of the specified image frame view
2164  * The description consists of the parent track name size and name,
2165  * the parent group name size and name, and the item name size and name
2166  *
2167  * @param ifv the item to string_compose a description of
2168  * @param buffer the buffer to write the description
2169  */
2170 void
2171 ImageFrameSocketHandler::compose_imageframe_item_desc(ImageFrameView* ifv, std::ostringstream& buffer)
2172 {
2173         buffer << std::setw(3) << ifv->get_time_axis_group()->get_view().trackview().name().length() ;
2174         buffer << ifv->get_time_axis_group()->get_view().trackview().name() ;
2175         
2176         // add the parent scene
2177         buffer << std::setw(3) << ifv->get_time_axis_group()->get_group_name().length() ;
2178         buffer << ifv->get_time_axis_group()->get_group_name() ;
2179         
2180         // add the ImageFrameItem id length and Id
2181         buffer << setw(3)  << ifv->get_item_name().length() ;
2182         buffer << ifv->get_item_name() ;
2183 }
2184
2185 /**
2186  * Compose a description of the specified marker view
2187  * The description consists of the parent track name size and name,
2188  * and the item name size and name
2189  *
2190  * @param mv the item to string_compose a description of
2191  * @param buffer the buffer to write the description
2192  */
2193 void
2194 ImageFrameSocketHandler::compose_marker_item_desc(MarkerView* mv, std::ostringstream& buffer)
2195 {
2196         MarkerTimeAxis* mta = dynamic_cast<MarkerTimeAxis*>(&mv->get_time_axis_view()) ;
2197         
2198         if(!mta)
2199         {
2200                 return ;
2201         }
2202         
2203         buffer << std::setw(3) << mta->name().length() ;
2204         buffer << mta->name() ;
2205         
2206         buffer << std::setw(3) << mv->get_item_name().length() ;
2207         buffer << mv->get_item_name() ; 
2208 }
2209
2210
2211 /**
2212  * Returns the ImageFrameView from the specified description
2213  * The errcode parameter is used to indicate the item which caused
2214  * an error on failure of this method
2215  * 0 = success
2216  * 1 = the track item was not found
2217  * 2 = the group item was not found
2218  * 3 = the imageframe item was not found
2219  *
2220  * @paran track_id the track on which the item is placed
2221  * @param group_id the group in which the item is a member
2222  * @param item_id the id of the item
2223  * @param int32_t reference used for error codes on failure
2224  * @param errmsg populated with a description of the error on failure
2225  * @return the described item on success, 0 otherwise
2226  */
2227 ImageFrameView*
2228 ImageFrameSocketHandler::get_imageframe_view_from_desc(const string & track_id, const string & group_id, const string & item_id, int& errcode, std::string& errmsg)
2229 {
2230         ImageFrameView* item = 0 ;
2231         
2232         // get the named time axis
2233         ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_id)) ;
2234         
2235         if(!ifta)
2236         {
2237                 errcode = 1 ;
2238                 errmsg = std::string("Image Frame Time Axis Not Found: ").append(track_id) ;
2239         }
2240         else
2241         {
2242                 // get the parent scene
2243                 ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(group_id) ;
2244                 if(!iftag)
2245                 {
2246                         errcode = 2 ;
2247                         errmsg = std::string("Image Frame Group Not Found: ").append(group_id) ;
2248                 }
2249                 else
2250                 {
2251                         ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ;
2252                         if(!ifv)
2253                         {
2254                                 errcode = 3 ;
2255                                 errmsg = std::string("Image Frame Item Not Found: ").append(item_id) ;
2256                         }
2257                         else
2258                         {
2259                                 // yay!!
2260                                 item = ifv ;
2261                                 errcode = 0 ;
2262                         }
2263                 }
2264         }
2265         
2266         return(item) ;
2267 }
2268
2269 //---------------------------------------------------------------------------------------//
2270 // Convenince Message Send Methods
2271
2272 #ifndef MSG_NOSIGNAL
2273 #define MSG_NOSIGNAL 0
2274 #endif
2275
2276 /**
2277  * Sends a message throught the socket
2278  *
2279  * @param msg the message to send
2280  * @return the return value of the socket call
2281  */
2282 int
2283 ImageFrameSocketHandler::send_message(const string & msg)
2284 {
2285         //std::cout << "Sending Message [" << msg << "]\n" ;
2286         int retcode = ::send(theArdourToCompositorSocket, msg.c_str(), msg.length(), MSG_NOSIGNAL) ;
2287         
2288         return(retcode) ;
2289 }
2290                 
2291 /**
2292  * Reads a message from the Socket
2293  *
2294  * @param msg a string to populate with the received message
2295  * @return the return value from the socket call
2296  */
2297 int
2298 ImageFrameSocketHandler::read_message(std::string& msg)
2299 {
2300         char buf[ardourvis::MAX_MSG_SIZE + 1] ;
2301         memset(buf, 0, (ardourvis::MAX_MSG_SIZE + 1)) ;
2302         
2303         msg = "" ;
2304         int retcode = ::recv(theArdourToCompositorSocket, buf, ardourvis::MAX_MSG_SIZE, 0) ;
2305         
2306         msg = buf ;
2307         //std::cout << "Received Message [" << msg << "]\n" ;
2308         
2309         return(retcode) ;
2310 }
2311
2312 /**
2313  * Reads a reply message ("RT0"/"RT1") from the Socket
2314  *
2315  * @return true if "RT0" was received,, otherwise false
2316  */
2317 bool
2318 ImageFrameSocketHandler::read_result()
2319 {
2320         char buf[(ardourvis::RETURN_MSG_SIZE)+1] ;
2321         int retcode = ::recv(theArdourToCompositorSocket, buf, ardourvis::RETURN_MSG_SIZE, 0) ;
2322         buf[ardourvis::RETURN_MSG_SIZE]='\0';
2323         if (retcode > 0) {
2324           std::cout << "Received Result [" << buf << "]\n" ;
2325           if (retcode == ardourvis::RETURN_MSG_SIZE && buf == ardourvis::RETURN_TRUE) {
2326             return (true);
2327           }
2328         }
2329         return(false) ;
2330 }
2331
2332 /**
2333  * Convenience method to string_compose and send a success messasge back to the Image Compositor
2334  *
2335  */
2336 void
2337 ImageFrameSocketHandler::send_return_success()
2338 {
2339         send_message(ardourvis::RETURN_TRUE) ;
2340 }
2341
2342 /**
2343  * Convenience method to string_compose and send a failure messasge back to the Image Compositor
2344  *
2345  * @param msg the failure message
2346  */
2347 void
2348 ImageFrameSocketHandler::send_return_failure(const std::string& msg)
2349 {
2350         std::ostringstream buf ;
2351         buf << std::setfill('0') ;
2352         buf << ardourvis::RETURN_FALSE ;
2353         buf << std::setw(3) << msg.length(); ;
2354         buf << msg ;
2355         
2356         send_message(buf.str()) ;
2357 }