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