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