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