13
0
livetrax/gtk2_ardour/imageframe_socket_handler.cc
David Robillard fe13d08874 Large nasty commit in the form of a 5000 line patch chock-full of completely
unecessary changes.  (Sorry, doing a "sprint" based thing, this is the end of the first one)

Achieved MIDI track and bus creation, associated Jack port and diskstream creation, and minimal GUI stuff for creating them.  Should be set to start work on actually recording and playing midi to/from disk now.

Relevant (significant) changes:

- Creation of a Buffer class.  Base class is type agnostic so things can point to a buffer but not care what kind it is (otherwise it'd be a template).  Derived into AudioBuffer and MidiBuffer, with a type tag because checking type is necessary in parts of the code where dynamic_cast wouldn't be wise.  Originally I considered this a hack, but passing around a type proved to be a very good solution to all the other problems (below).  There is a 1:1 mapping between jack port data types and ardour Buffer types (with a conversion function), but that's easily removed if it ever becomes necessary.  Having the type scoped in the Buffer class is maybe not the best spot for it, but whatever (this is proof of concept kinda stuff right now...)

- IO now has a "default" port type (passed to the constructor and stored as a member), used by ensure_io (and similar) to create n ports.  IO::register_***_port has a type argument that defaults to the default type if not passed.  Rationale:  previous IO API is identical, no changes needed to existing code, but path is paved for multiple port types in one IO, which we will need for eg synth plugin inserts, among other things.  This is not quite ideal (best would be to only have the two port register functions and have them take a type), but the alternative is a lot of work (namely destroying the 'ensure' functions and everything that uses them) for very little gain.  (I am convinced after quite a few tries at the whiteboard that subclassing IO in any way is not a feasible option, look at it's inheritance diagram in Doxygen and you can see why)

- AudioEngine::register_audio_input_port is now register_input_port and takes a type argument.  Ditto for output.

- (Most significant change) AudioDiskstream abstracted into Distream, and sibling MidiDiskstream created.  Very much still a work in progress, but Diskstream is there to switch references over to (most already are), which is the important part.  It is still unclear what the MIDI diskstream's relation to channels is, but I'm pretty sure they will be single channel only (so SMF Type 0) since noone can come up with a reason otherwise.

- MidiTrack creation.  Same thing as AudioTrack but with a different default type basically.  No big deal here.

- Random cleanups and variable renamings etc. because I have OCD and can't help myself. :)

Known broken:  Loading of sessions containing MIDI tracks.




git-svn-id: svn://localhost/ardour2/branches/midi@641 d708f5d6-7413-0410-9779-e7cbd77b26cf
2006-06-26 16:01:34 +00:00

2354 lines
60 KiB
C++

/*
Copyright (C) 2003 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
*/
#include <iostream>
#include <iomanip>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <cstdio>
#include <sigc++/bind.h>
#include <gtkmm2ext/gtk_ui.h>
#include "imageframe_socket_handler.h"
#include "imageframe_time_axis.h"
#include "imageframe_time_axis_view.h"
#include "imageframe_time_axis_group.h"
#include "imageframe_view.h"
#include "marker_time_axis.h"
#include "marker_time_axis_view.h"
#include "ardour_ui.h"
#include "public_editor.h"
#include "gui_thread.h"
#include "i18n.h"
#include <ardour/session.h>
#include <unistd.h>
using namespace std;
using namespace ardourvis ;
using namespace sigc;
using namespace ARDOUR;
using namespace PBD;
ImageFrameSocketHandler* ImageFrameSocketHandler::_instance = 0 ;
/**
* Constructs a new ImageFrameSocketHandler to handle communication between Ardour and the Image Compositor
*
* @param ed the PublicEditor
*/
ImageFrameSocketHandler::ImageFrameSocketHandler(PublicEditor& ed) : thePublicEditor(ed), theArdourToCompositorSocket(-1)
{
}
/**
* Descructor
* this will shutdown the socket if open
*/
ImageFrameSocketHandler::~ImageFrameSocketHandler()
{
close_connection() ;
}
/**
* Returns the instance of the ImageFrameSocketHandler
* the instance should first be created with createInstance
*
* @return the instance of the ImageFrameSocketHandler
*/
ImageFrameSocketHandler*
ImageFrameSocketHandler::get_instance()
{
return(_instance) ;
}
/**
* Create an new instance of the ImageFrameSocketHandler, if one does not already exist
*
* @param ed the Ardour PublicEditor
*/
ImageFrameSocketHandler*
ImageFrameSocketHandler::create_instance(PublicEditor& ed)
{
if(_instance)
{
return(_instance) ;
}
else
{
_instance = new ImageFrameSocketHandler(ed) ;
return(_instance) ;
}
}
/**
* call back to handle doing the processing work
* This method is added to the gdk main loop and called when there is data
* upon the socket.
*
*/
void
ImageFrameSocketHandler::image_socket_callback(void *arg, int32_t fd, GdkInputCondition cond)
{
char buf[ardourvis::MAX_MSG_SIZE + 1] ;
memset(buf, 0, (ardourvis::MAX_MSG_SIZE + 1)) ;
buf[ardourvis::MAX_MSG_SIZE] = '\0' ;
int retcode = ::recv(fd, buf, MAX_MSG_SIZE, 0) ;
if (retcode == 0)
{
//end-of-file, other end closed or shutdown?
ARDOUR_UI::instance()->popup_error(_("Image Compositor Socket has been shutdown/closed"));
// assume socket has been shutdown, tell, someone interested,
// and remove the socket from the event loop
ImageFrameSocketHandler* ifsh = ImageFrameSocketHandler::get_instance() ;
gdk_input_remove(ifsh->theGdkInputTag) ;
ifsh->close_connection() ;
ifsh->CompositorSocketShutdown() ; /* EMIT_SIGNAL */
}
if(retcode > 0)
{
//std::cout << "Received Msg [" << buf << "]\n" ;
ImageFrameSocketHandler* ifsh = ImageFrameSocketHandler::get_instance() ;
std::string mType = ifsh->get_message_part(0,2,buf) ;
if(mType == ardourvis::INSERT_ITEM)
{
ifsh->handle_insert_message(buf) ;
}
else if (mType == ardourvis::REMOVE_ITEM)
{
ifsh->handle_remove_message(buf) ;
}
else if (mType == ardourvis::RENAME_ITEM)
{
ifsh->handle_rename_message(buf) ;
}
else if (mType == ardourvis::ITEM_UPDATE)
{
ifsh->handle_item_update_message(buf) ;
}
else if (mType == ardourvis::REQUEST_DATA)
{
ifsh->handle_request_data(buf) ;
}
else if (mType == ardourvis::ITEM_SELECTED)
{
ifsh->handle_item_selected(buf) ;
}
else if(mType == ardourvis::SESSION_ACTION)
{
ifsh->handle_session_action(buf) ;
}
else
{
std::string errMsg = "Unknown Message type : " ;
errMsg.append(mType) ;
ifsh->send_return_failure(errMsg) ;
}
}
}
/**
* Attempt to connect to the image compositor on the specified host and port
*
* @param hostIp the ip address of the image compositor host
* @param port the oprt number to attemp the connection on
* @return true if the connection was a succees
* false otherwise
*/
bool
ImageFrameSocketHandler::connect(const char * hostIp, int32_t port)
{
if (is_connected())
{
//already connected...
return(true) ;
}
theArdourToCompositorSocket = socket(AF_INET, SOCK_STREAM, 0) ;
if(theArdourToCompositorSocket == -1)
{
return(false) ;
}
int on = 1 ;
setsockopt(theArdourToCompositorSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) ;
sockaddr_in m_addr ;
m_addr.sin_family = AF_INET ;
m_addr.sin_port = htons(port) ;
m_addr.sin_addr.s_addr = inet_addr(hostIp) ;
int status = ::connect(theArdourToCompositorSocket, (sockaddr *) &m_addr, sizeof(m_addr)) ;
if(status == -1)
{
theArdourToCompositorSocket = -1 ;
return(false) ;
}
return(true) ;
}
/**
* Closes the connection to th Image Compositor
*
*/
void
ImageFrameSocketHandler::close_connection()
{
if(is_connected())
{
::close(theArdourToCompositorSocket) ;
theArdourToCompositorSocket = -1 ;
}
}
/**
* Returns true if this ImagFrameSocketHandler is currently connected to rthe image compositor
*
* @return true if connected to the image compositor
*/
bool
ImageFrameSocketHandler::is_connected()
{
return(theArdourToCompositorSocket == -1 ? false : true) ;
}
/**
* Sets the tag used to describe this input within gtk
* this is returned when gdk_input_add is called and is required to remove the input
*
* @param tag the gdk input tag of this input
*/
void
ImageFrameSocketHandler::set_gdk_input_tag(int tag)
{
theGdkInputTag = tag ;
}
/**
* Returns the gdk input tag of this input
*
* @return the gdk input tag of this input
* @see setGdkInputTag
*/
int
ImageFrameSocketHandler::get_gdk_input_tag()
{
return(theGdkInputTag) ;
}
/**
* Returns the socket file descriptor
*
* @return the Sockt file descriptor
*/
int
ImageFrameSocketHandler::get_socket_descriptor()
{
return(theArdourToCompositorSocket) ;
}
//---------------------------------------------------------------------------------------//
// Handle Sending messages to the Image Compositor
//----------------------------
// ImageFrameTimeAxis Messages
/**
* Sends a message stating that the named image frame time axis has been removed
*
* @param track_id the unique id of the removed image frame time axis
* @param src the identity of the object that initiated the change
*/
void
ImageFrameSocketHandler::send_imageframe_time_axis_removed(const string & track_id, void* src)
{
if(this == src || src == 0)
{
// ie the change originated from us, then dont send any message back
return ;
}
// create a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::IMAGEFRAME_TIME_AXIS ;
// add the id length, and the id
msgBuffer << std::setw(3) << track_id.length() ;
msgBuffer << track_id ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
/**
* Sends a message indicating that an ImageFrameTimeAxis has been renamed
*
* @param new_id the new name, or Id, of the track
* @param old_id the old name, or Id, of the track
* @param src the identity of the object that initiated the change
* @param time_axis the time axis that has changed
*/
void
ImageFrameSocketHandler::send_imageframe_time_axis_renamed(const string & new_id, const string & old_id, void* src, ImageFrameTimeAxis* time_axis)
{
// ENSURE_GUI_THREAD(SigC::bind (mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_renamed), new_id, old_id, src, time_axis));
if(this == src || src == 0)
{
// ie the change originated from us, then dont send any message back
return ;
}
// create a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::RENAME_ITEM << ardourvis::IMAGEFRAME_TIME_AXIS ;
// add the old id and length
msgBuffer << std::setw(3) << old_id.length() ;
msgBuffer << old_id ;
// add the new id and length
msgBuffer << std::setw(3) << new_id.length() ;
msgBuffer << new_id ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
//------------------------
// MarkerTimeAxis Messages
/**
* Sends a message stating that the named marker time axis has been removed
*
* @param track_id the unique id of the removed image frame time axis
* @param src the identity of the object that initiated the change
*/
void
ImageFrameSocketHandler::send_marker_time_axis_removed(const string & track_id, void* src)
{
if(this == src || src == 0)
{
// ie the change originated from us, then dont send any message back
return ;
}
// create a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::MARKER_TIME_AXIS ;
// add the id length, and the id
msgBuffer << std::setw(3) << track_id.length() ;
msgBuffer << track_id ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
/**
* Sends a message indicating that an MarkerTimeAxis has been renamed
*
* @param new_id the new name, or Id, of the track
* @param old_id the old name, or Id, of the track
* @param src the identity of the object that initiated the change
* @param time_axis the time axis that has changed
*/
void
ImageFrameSocketHandler::send_marker_time_axis_renamed(const string & new_id, const string & old_id, void* src, MarkerTimeAxis* time_axis)
{
// ENSURE_GUI_THREAD(bind (mem_fun(*this, &ImageFrameSocketHandler::send_marker_time_axis_renamed), new_id, old_id, src, time_axis));
if(this == src || src == 0)
{
// ie the change originated from us, then dont send any message back
return ;
}
// ctreate a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::RENAME_ITEM << ardourvis::MARKER_TIME_AXIS ;
// add the old id and length
msgBuffer << std::setw(3) << old_id.length() ;
msgBuffer << old_id ;
// add the new id and length
msgBuffer << std::setw(3) << new_id.length() ;
msgBuffer << new_id ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
//---------------------------------
// ImageFrameTimeAxisGroup Messages
/**
* Sends a message stating that the group has been removed
*
* @param group_id the unique id of the removed image frame time axis
* @param src the identity of the object that initiated the change
* @param group the group that has changed
*/
void
ImageFrameSocketHandler::send_imageframe_time_axis_group_removed(const string & group_id, void* src, ImageFrameTimeAxisGroup* group)
{
if(this == src || src == 0)
{
// ie the change originated from us, then dont send any message back
return ;
}
// create a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::IMAGEFRAME_GROUP ;
// add the id length, and the id of the parent image time axis
std::string track_id = group->get_view().trackview().name() ;
msgBuffer << std::setw(3) << track_id.length() ;
msgBuffer << track_id ;
// add the group id and length
msgBuffer << std::setw(3) << group_id.length() ;
msgBuffer << group_id ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
/**
* Send a message indicating that an ImageFrameTimeAxisGroup has been renamed
*
* @param new_id the new name, or Id, of the group
* @param old_id the old name, or Id, of the group
* @param src the identity of the object that initiated the change
* @param group the group that has changed
*/
void
ImageFrameSocketHandler::send_imageframe_time_axis_group_renamed(const string & new_id, const string & old_id, void* src, ImageFrameTimeAxisGroup* group)
{
// ENSURE_GUI_THREAD(bind (mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_group_renamed), new_id, old_id, src, group));
if(this == src || src == 0)
{
// ie the change originated from us, then dont send any message back
return ;
}
// ctreate a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::RENAME_ITEM << ardourvis::IMAGEFRAME_GROUP ;
// add the track this group is upon
std::string track_id = group->get_view().trackview().name() ;
msgBuffer << std::setw(3) << track_id.length() << track_id ;
// add the old id and length
msgBuffer << std::setw(3) << old_id.length() ;
msgBuffer << old_id ;
// add the new id and length
msgBuffer << std::setw(3) << new_id.length() ;
msgBuffer << new_id ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
//---------------------------------
// ImageFrameView Messages
/**
* Send an Image Frame View Item position changed message
*
* @param pos the new position value
* @param src the identity of the object that initiated the change
* @param item the time axis item whos position has changed
*/
void
ImageFrameSocketHandler::send_imageframe_view_position_change(jack_nframes_t pos, void* src, ImageFrameView* item)
{
// ENSURE_GUI_THREAD(bind (mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_view_position_change), pos, src, item));
if(this == src || src == 0)
{
return ;
}
// create a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::IMAGEFRAME_ITEM << ardourvis::POSITION_CHANGE ;
// add the item description
this->compose_imageframe_item_desc(item, msgBuffer) ;
msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << pos ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
/**
* Send a Image Frame View item duration changed message
*
* @param dur the the new duration value
* @param src the identity of the object that initiated the change
* @param item the item which has had a duration change
*/
void
ImageFrameSocketHandler::send_imageframe_view_duration_change(jack_nframes_t dur, void* src, ImageFrameView* item)
{
// ENSURE_GUI_THREAD(bind (mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_view_duration_change), dur, src, item));
if(this == src || src == 0)
{
return ;
}
// create a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::IMAGEFRAME_ITEM << ardourvis::DURATION_CHANGE ;
this->compose_imageframe_item_desc(item, msgBuffer) ;
msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << dur ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
/**
* Send a message indicating that an ImageFrameView has been renamed
*
* @param item the ImageFrameView which has been renamed
* @param src the identity of the object that initiated the change
* @param item the renamed item
*/
void
ImageFrameSocketHandler::send_imageframe_view_renamed(const string & new_id, const string & old_id, void* src, ImageFrameView* item)
{
if(this == src || src == 0)
{
// ie the change originated from us, then dont send any message back
return ;
}
// ctreate a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::RENAME_ITEM << ardourvis::IMAGEFRAME_ITEM ;
this->compose_imageframe_item_desc(item, msgBuffer) ;
// add the old id and length
msgBuffer << std::setw(3) << old_id.length() ;
msgBuffer << old_id ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
/**
* Send a message indicating that an ImageFrameView item has been removed message
*
* @param item_id the id of the item that was removed
* @param item the removed item
*/
void
ImageFrameSocketHandler::send_imageframe_view_removed(const string & item_id, void* src, ImageFrameView* item)
{
if(this == src || src == 0)
{
// ie the change originated from us, then dont send any message back
return ;
}
// create a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::IMAGEFRAME_ITEM ;
// add the id length, and the id
ImageFrameTimeAxisGroup* parentGroup = item->get_time_axis_group() ;
std::string group_id = parentGroup->get_group_name() ;
std::string track_id = parentGroup->get_view().trackview().name() ;
msgBuffer << std::setw(3) << track_id.length() << track_id ;
msgBuffer << std::setw(3) << group_id.length() << group_id ;
msgBuffer << std::setw(3) << item_id.length() << item_id ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
//---------------------------------
// MarkerView Messages
/**
* Send a Marker View Item position changed message
*
* @param pos the new position value
* @param src the identity of the object that initiated the change
* @param item the time axis item whos position has changed
*/
void
ImageFrameSocketHandler::send_marker_view_position_change(jack_nframes_t pos, void* src, MarkerView* item)
{
if(this == src || src == 0)
{
return ;
}
// create a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::MARKER_ITEM << ardourvis::POSITION_CHANGE ;
// add the item description
this->compose_marker_item_desc(item, msgBuffer) ;
msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << pos ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
/**
* Send a Marker View item duration changed message
*
* @param dur the new duration value
* @param src the identity of the object that initiated the change
* @param item the time axis item whos position has changed
*/
void
ImageFrameSocketHandler::send_marker_view_duration_change(jack_nframes_t dur, void* src, MarkerView* item)
{
if(this == src || src == 0)
{
return ;
}
// create a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::MARKER_ITEM << ardourvis::DURATION_CHANGE ;
this->compose_marker_item_desc(item, msgBuffer) ;
msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << dur ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
/**
* Send a message indicating that a MarkerView has been renamed
*
* @param new_id the new_id of the object
* @param old_id the old_id of the object
* @param src the identity of the object that initiated the change
* @param item the MarkerView which has been renamed
*/
void
ImageFrameSocketHandler::send_marker_view_renamed(const string & new_id, const string & old_id, void* src, MarkerView* item)
{
if(this == src || src == 0)
{
// ie the change originated from us, then dont send any message back
return ;
}
// ctreate a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::RENAME_ITEM << ardourvis::MARKER_ITEM ;
this->compose_marker_item_desc(item, msgBuffer) ;
// add the old id and length
msgBuffer << std::setw(3) << old_id.length() ;
msgBuffer << old_id ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
/**
* Send a message indicating that a MarkerView item has been removed message
*
* @param item_id the id of the item that was removed
* @param src the identity of the object that initiated the change
* @param item the MarkerView which has been removed
*/
void
ImageFrameSocketHandler::send_marker_view_removed(const string & item_id, void* src, MarkerView* item)
{
if(this == src || src == 0)
{
// ie the change originated from us, then dont send any message back
return ;
}
// create a message buffer
std::ostringstream msgBuffer ;
msgBuffer << std::setfill('0') ;
// add the msg type
msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::MARKER_ITEM ;
// add the id length, and the id
std::string track_id = item->get_time_axis_view().name() ;
msgBuffer << std::setw(3) << track_id.length() << track_id ;
msgBuffer << std::setw(3) << item_id.length() << item_id ;
send_message(msgBuffer.str()) ;
// XXX should do something with the return
std::string retmsg ;
read_message(retmsg) ;
}
//---------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------//
// Message breakdown ie avoid a big if...then...else
/**
* Handle insert item requests
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_insert_message(const char* msg)
{
// handle the insert item message
// determine the object type to insert based upon characters 2-3
std::string oType = get_message_part(2,2,msg) ;
if(oType == ardourvis::IMAGEFRAME_TIME_AXIS)
{
this->handle_insert_imageframe_time_axis(msg) ;
}
else if (oType == ardourvis::MARKER_TIME_AXIS)
{
this->handle_insert_marker_time_axis(msg) ;
}
else if (oType == ardourvis::IMAGEFRAME_GROUP)
{
this->handle_insert_imageframe_group(msg) ;
}
else if (oType == ardourvis::IMAGEFRAME_ITEM)
{
this->handle_insert_imageframe_view(msg) ;
}
else if (oType == ardourvis::MARKER_ITEM)
{
this->handle_insert_marker_view(msg) ;
}
else
{
std::string errMsg = "Unknown Object type during insert: " ;
errMsg.append(oType) ;
send_return_failure(errMsg) ;
}
}
/**
* Handle remove item requests
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_remove_message(const char* msg)
{
// handle the removal of an item message
// determine the object type to remove based upon characters 2-3
std::string oType = get_message_part(2,2,msg) ;
if(oType == ardourvis::IMAGEFRAME_TIME_AXIS)
{
this->handle_remove_imageframe_time_axis(msg) ;
}
else if (oType == ardourvis::MARKER_TIME_AXIS)
{
this->handle_remove_marker_time_axis(msg) ;
}
else if (oType == ardourvis::IMAGEFRAME_ITEM)
{
this->handle_remove_imageframe_view(msg) ;
}
else if (oType == ardourvis::MARKER_ITEM)
{
this->handle_remove_marker_view(msg) ;
}
else
{
std::string errMsg = "Unknown Object type during Remove: " ;
errMsg.append(oType) ;
send_return_failure(errMsg) ;
}
}
/**
* Handle rename item requests
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_rename_message(const char* msg)
{
// handle the renaming of an item message
// determine the object type to rename based upon characters 2-3
std::string oType = get_message_part(2,2,msg) ;
if(oType == ardourvis::IMAGEFRAME_TIME_AXIS)
{
this->handle_rename_imageframe_time_axis(msg) ;
}
else if (oType == ardourvis::MARKER_TIME_AXIS)
{
this->handle_rename_marker_time_axis(msg) ;
}
else if (oType == ardourvis::IMAGEFRAME_ITEM)
{
this->handle_rename_imageframe_view(msg) ;
}
else if (oType == ardourvis::MARKER_ITEM)
{
this->handle_rename_marker_view(msg) ;
}
else
{
std::string errMsg = "Unknown Object type during Rename: " ;
errMsg.append(oType) ;
send_return_failure(errMsg) ;
}
}
/**
* Handle a request for session information
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_request_data(const char* msg)
{
// determine the request type
std::string reqType = get_message_part(2,2,msg) ;
if(reqType == ardourvis::SESSION_NAME)
{
handle_session_name_request(msg) ;
}
}
/**
* Handle the update of a particular item
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_item_update_message(const char* msg)
{
// determin the object that requires updating, characters 2-3
std::string oType = get_message_part(2,2,msg) ;
// What needs updating? chars 4-5
std::string attr = get_message_part(4,2,msg) ;
if(oType == ardourvis::IMAGEFRAME_ITEM)
{
if(attr == ardourvis::POSITION_CHANGE)
{
handle_imageframe_view_position_update(msg) ;
}
else if(attr == ardourvis::DURATION_CHANGE)
{
handle_imageframe_view_duration_update(msg) ;
}
else if(attr == ardourvis::POSITION_LOCK_CHANGE)
{
handle_imageframe_position_lock_update(msg) ;
}
else if(attr == ardourvis::MAX_DURATION_CHANGE)
{
handle_imageframe_view_max_duration_update(msg) ;
}
else if(attr == ardourvis::MAX_DURATION_ENABLE_CHANGE)
{
handle_imageframe_view_max_duration_enable_update(msg) ;
}
else if(attr == ardourvis::MIN_DURATION_CHANGE)
{
handle_imageframe_view_min_duration_update(msg) ;
}
else if(attr == ardourvis::MIN_DURATION_ENABLE_CHANGE)
{
handle_imageframe_view_min_duration_enable_update(msg) ;
}
else
{
std::string errMsg = "Unknown Attribute during Item Update: " ;
errMsg.append(oType) ;
send_return_failure(errMsg) ;
}
}
else if(oType == ardourvis::MARKER_ITEM)
{
if(attr == ardourvis::POSITION_CHANGE)
{
handle_marker_view_position_update(msg) ;
}
else if(attr == ardourvis::DURATION_CHANGE)
{
handle_marker_view_duration_update(msg) ;
}
else
{
std::string errMsg = "Unknown Attribute during Item Update: " ;
errMsg.append(oType) ;
send_return_failure(errMsg) ;
}
}
else
{
std::string errMsg = "Unknown Object type during Item Update: " ;
errMsg.append(oType) ;
send_return_failure(errMsg) ;
}
}
/**
* Handle the selection of an Item
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_item_selected(const char* msg)
{
// determine the object that requires updating, characters 2-3
std::string oType = get_message_part(2,2,msg) ;
if(oType == std::string(ardourvis::IMAGEFRAME_ITEM))
{
int position = 4 ; // message type chars
std::string track_id ;
std::string scene_id ;
std::string item_id ;
int track_id_size ;
int scene_id_size ;
int item_id_size ;
this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, scene_id, scene_id_size, item_id, item_id_size) ;
// get the named time axis
ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_id)) ;
if(!ifta)
{
send_return_failure(std::string("No parent Image Track found : ").append(track_id)) ;
}
else
{
// get the parent scene
ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_id) ;
if(!iftag)
{
send_return_failure(std::string("No parent Scene found : ").append(scene_id)) ;
}
else
{
ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ;
if(!ifv)
{
send_return_failure(std::string("No Image Frame Item found : ").append(item_id)) ;
}
else
{
ifv->set_selected(true) ;
ifta->get_view()->set_selected_imageframe_view(iftag, ifv) ;
thePublicEditor.scroll_timeaxis_to_imageframe_item(ifv) ;
send_return_success() ;
}
}
}
}
}
/**
* Handle s session action message
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_session_action(const char* msg)
{
std::string actionType = get_message_part(2,2,msg) ;
if(actionType == ardourvis::OPEN_SESSION)
{
this->handle_open_session(msg) ;
}
}
//---------------------------------------------------------------------------------------//
// handlers for specific insert procedures
/**
* Handle the insertion of a new ImaegFrameTimeAxis
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_insert_imageframe_time_axis(const char* msg)
{
int position = 4 ; // message type chars
// get the ImageFrameTrack name size
int track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
position += ardourvis::TEXT_SIZE_CHARS ;
// get the image frame track name
std::string track_name = get_message_part(position, track_name_size, msg) ;
position += track_name_size ;
// check we dont already have an time axis with that name
TimeAxisView* tav = thePublicEditor.get_named_time_axis(track_name) ;
if(tav)
{
std::string errmsg("Track already exists: ") ;
errmsg.append(track_name) ;
send_return_failure(errmsg) ;
}
else
{
thePublicEditor.add_imageframe_time_axis(track_name, this) ;
TimeAxisView* new_tav = thePublicEditor.get_named_time_axis(track_name) ;
if(new_tav)
{
ImageFrameTimeAxis* ifta = (ImageFrameTimeAxis*)new_tav ;
ifta->VisualTimeAxisRemoved.connect(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_removed)) ;
ifta->NameChanged.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_renamed), ifta)) ;
send_return_success() ;
}
else
{
std::string msg("Addition Failed: ") ;
msg.append(track_name) ;
send_return_failure(msg) ;
}
}
}
/**
* Handle the insertion of a new MarkerTimeAxis
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_insert_marker_time_axis(const char* msg)
{
int position = 4 ; // message type chars
// get the ImageFrameTrack name size
int track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
position += ardourvis::TEXT_SIZE_CHARS ;
// get the image frame track name
std::string track_name = get_message_part(position, track_name_size, msg) ;
position += track_name_size ;
// get the size of the name of the associated track
int assoc_track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
position += ardourvis::TEXT_SIZE_CHARS ;
// get the name of the track we associate the marker track with
std::string assoc_track_name = get_message_part(position, assoc_track_name_size, msg) ;
position += assoc_track_name_size ;
// check that we dont already have a time axis with that name
TimeAxisView* checkTav = thePublicEditor.get_named_time_axis(track_name) ;
if(checkTav)
{
std::string errmsg("Track already exists: ") ;
errmsg.append(track_name) ;
send_return_failure(errmsg) ;
}
else
{
// check the associated time axis exists
TimeAxisView* assoc_tav = thePublicEditor.get_named_time_axis(assoc_track_name) ;
if(assoc_tav)
{
thePublicEditor.add_imageframe_marker_time_axis(track_name, assoc_tav, this) ;
TimeAxisView* new_tav = thePublicEditor.get_named_time_axis(track_name) ;
bool added = false ;
if(new_tav)
{
MarkerTimeAxis* mta = dynamic_cast<MarkerTimeAxis*>(new_tav) ;
if(mta)
{
added = true ;
mta->VisualTimeAxisRemoved.connect(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_marker_time_axis_removed)) ;
mta->NameChanged.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_marker_time_axis_renamed), mta)) ;
}
}
if(added)
{
std::string msg("Addition Failed: ") ;
msg.append(track_name) ;
send_return_failure(msg) ;
}
}
else
{
std::string errmsg("No associated Track Found: ") ;
errmsg.append(track_name) ;
send_return_failure(errmsg) ;
}
}
}
/**
* Handle the insertion of a time axis group (a scene)
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_insert_imageframe_group(const char* msg)
{
int position = 4 ; // message type chars
// get the ImageFrameTrack name size
int track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
position += ardourvis::TEXT_SIZE_CHARS ;
// get the image frame track name
std::string track_name = get_message_part(position, track_name_size, msg) ;
position += track_name_size ;
// get the scene id size
int scene_id_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
position += ardourvis::TEXT_SIZE_CHARS ;
// get the scene id
std::string scene_id = get_message_part(position, scene_id_size, msg) ;
position += scene_id_size ;
// get the named ImageFrameTrack
ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_name)) ;
// check we got a valid ImageFrameTimeAxis
if(!ifta)
{
send_return_failure(std::string("No Image Frame Time Axis Found: ").append(track_name)) ;
return ;
}
ImageFrameTimeAxisGroup* iftag = ifta->get_view()->add_imageframe_group(scene_id, this) ;
if(!iftag)
{
send_return_failure(std::string("Image Frame Group insert failed")) ;
}
else
{
iftag->NameChanged.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_group_renamed), iftag)) ;
iftag->GroupRemoved.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_group_removed), iftag)) ;
send_return_success() ;
}
}
/**
* Handle the insertion of a new ImageFrameItem
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_insert_imageframe_view(const char* msg)
{
int position = 4 ; // message type chars
// get the ImageFrameTrack name size
int track_name_size = atoi(get_message_part(position,3,msg).c_str()) ;
position += 3 ;
// get the ImageFrameTrack Name
std::string imageframe_track_name = get_message_part(position,track_name_size,msg) ;
position += track_name_size ;
// get the scene name size
int scene_size = atoi(get_message_part(position,3,msg).c_str()) ;
position += 3 ;
// get the scene Name
std::string scene_name = get_message_part(position,scene_size,msg) ;
position += scene_size ;
// get the image frame_id size
int image_id_size = atoi(get_message_part(position,3,msg).c_str()) ;
position += 3 ;
// get the image frame_id
std::string image_id = get_message_part(position,image_id_size,msg) ;
position += image_id_size ;
// get the start frame value
jack_nframes_t start = strtoul((get_message_part(position,10,msg).c_str()),0,10) ;
position += 10 ;
// get the duration value
jack_nframes_t duration = strtoul((get_message_part(position,10,msg).c_str()),0,10) ;
position += 10 ;
//get the named time axis view we about to add an image to
TimeAxisView* tav = thePublicEditor.get_named_time_axis(imageframe_track_name) ;
ImageFrameTimeAxis* ifta = 0 ;
if(tav)
{
ifta = dynamic_cast<ImageFrameTimeAxis*>(tav) ;
}
if(!ifta)
{
std::string errmsg("No Parent Image Track Found: ") ;
errmsg.append(imageframe_track_name) ;
send_return_failure(errmsg) ;
// dont really like all these returns mid-way
// but this is goinf to get awfully if..then nested if not
return ;
}
// check the parent group exists
ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_name) ;
if(!iftag)
{
std::string errmsg("No Image Frame Group Found: ") ;
errmsg.append(scene_name) ;
send_return_failure(errmsg) ;
return ;
}
// ok, so we have the parent group and track, now we need dome image data
//
// request the image data from the image compositor
//
// ctreate a message buffer
std::ostringstream reqBuffer ;
reqBuffer << std::setfill('0') ;
// add the msg type
reqBuffer << REQUEST_DATA << IMAGE_RGB_DATA ;
// add the image track and size
reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << track_name_size ;
reqBuffer << imageframe_track_name ;
// add the scene id and size
reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << scene_size ;
reqBuffer << scene_name ;
// add the image id and size
reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << image_id_size ;
reqBuffer << image_id ;
// add the preferred image height
reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << ifta->get_image_display_height() ;
// send the request message
send_message(reqBuffer.str()) ;
// read the reply, the inital image data message
// this gives us the image dimensions and the expected size of the image data
// msg type(4) + image width(3) + height(3) + num channels(3) + size of the image data (32)
std::string init_image_data_msg ;
read_message(init_image_data_msg) ;
int init_msg_pos = 4 ;
int imgWidth = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_SIZE_CHARS).c_str()) ;
init_msg_pos += ardourvis::IMAGE_SIZE_CHARS ;
int imgHeight = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_SIZE_CHARS).c_str()) ;
init_msg_pos += ardourvis::IMAGE_SIZE_CHARS ;
int imgChannels = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_SIZE_CHARS).c_str()) ;
init_msg_pos += ardourvis::IMAGE_SIZE_CHARS ;
int imgSize = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_DATA_MESSAGE_SIZE_CHARS).c_str()) ;
// send a success msg
// we need to do this to keep things moving
send_return_success() ;
// create our image rgb buffer, this holds the image data we receive
unsigned char* rgb_img_buf = new unsigned char[imgSize] ;
int retcode = ::recv(theArdourToCompositorSocket, rgb_img_buf, imgSize, MSG_WAITALL) ;
if(retcode != imgSize)
{
delete [] rgb_img_buf ;
send_return_failure("Could not create new Image Frame View : image data sizes did not match") ;
}
else
{
ImageFrameView* ifv = iftag->add_imageframe_item(image_id, start, duration, rgb_img_buf, (uint32_t)imgWidth, (uint32_t)imgHeight, (uint32_t)imgChannels, this) ;
if(ifv)
{
ifv->PositionChanged.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_view_position_change), ifv)) ;
ifv->DurationChanged.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_view_duration_change), ifv)) ;
ifv->ItemRemoved.connect(sigc::bind(sigc::mem_fun(*this, &ImageFrameSocketHandler::send_imageframe_view_removed), ifv)) ;
send_return_success() ;
}
else
{
//addition failed. assume duplicate item_id
send_return_failure("Could not create new Image Frame View") ;
}
}
}
/**
* Handle the insertion of a new MarkerItem
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_insert_marker_view(const char* msg)
{}
//---------------------------------------------------------------------------------------//
// handlers for specific removal procedures
/**
* Handle the removal of an ImageTimeAxis
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_remove_imageframe_time_axis(const char* msg)
{}
/**
* Handle the removal of an MarkerTimeAxis
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_remove_marker_time_axis(const char* msg)
{}
/**
* Handle the removal of an ImageFrameTimeAxisGroup
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_remove_imageframe_time_axis_group(const char* msg)
{}
/**
* Handle the removal of an ImageFrameItem
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_remove_imageframe_view(const char* msg)
{}
/**
* Handle the removal of an MarkerItem
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_remove_marker_view(const char* msg)
{}
//---------------------------------------------------------------------------------------//
// handlers for the specific rename procedures
/**
* Handle the renaming of an ImageTimeAxis
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_rename_imageframe_time_axis(const char* msg)
{
// msg [MVIT][oldSize][oldId][newSize][newId]
int position = 4 ; // message type chars
// get the old Id size
int old_id_size = atoi(get_message_part(position,3,msg).c_str()) ;
position += 3 ;
// get the old id
std::string old_id = get_message_part(position,old_id_size,msg) ;
position += old_id_size ;
//get the new Id size
int new_id_size = atoi(get_message_part(position,3,msg).c_str()) ;
position += 3 ;
// get the new Id
std::string new_id = get_message_part(position,new_id_size,msg) ;
position += new_id_size ;
// get the Named time axis
TimeAxisView* tav = thePublicEditor.get_named_time_axis(old_id) ;
if(dynamic_cast<ImageFrameTimeAxis*>(tav))
{
ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(tav) ;
ifta->set_time_axis_name(new_id, this) ;
send_return_success() ;
}
else
{
std::string msg = "No Image Track Found: " ;
msg.append(old_id) ;
send_return_failure(msg) ;
}
}
/**
* Handle the renaming of an MarkerTimeAxis
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_rename_marker_time_axis(const char* msg)
{}
/**
* Handle the renaming of an ImageFrameItem
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_rename_imageframe_time_axis_group(const char* msg)
{}
/**
* Handle the renaming of an ImageFrameItem
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_rename_imageframe_view(const char* msg)
{}
/**
* Handle the renaming of an Marker
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_rename_marker_view(const char* msg)
{}
//---------------------------------------------------------------------------------------//
// handlers for data request
/**
* Handle a request for the sessnio naem fo the current session
* We return a failure state if no session is open
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_session_name_request(const char* msg)
{
ARDOUR::Session* currentSession = thePublicEditor.current_session() ;
if(currentSession == 0)
{
// no current session, return failure
std::string msg("No Current Session") ;
send_return_failure(msg) ;
}
else
{
std::string sessionName = currentSession->name() ;
std::string sessionPath = currentSession->path() ;
if(sessionPath[sessionPath.length() -1] != '/')
{
sessionPath.append("/") ;
}
sessionPath.append(sessionName) ;
std::ostringstream msgBuf ;
msgBuf << ardourvis::RETURN_DATA << ardourvis::SESSION_NAME ;
msgBuf << std::setfill('0') ;
msgBuf << std::setw(ardourvis::TEXT_SIZE_CHARS) << sessionPath.length() ;
msgBuf << sessionPath ;
send_message(msgBuf.str()) ;
}
}
//---------------------------------------------------------------------------------------//
// handlers for specific item update changes
/**
* Handle ImageFrameView positional changes
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_imageframe_view_position_update(const char* msg)
{
int position = 6 ; // message type chars
std::string track_id ;
std::string scene_id ;
std::string item_id ;
int track_id_size ;
int scene_id_size ;
int item_id_size ;
this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, scene_id, scene_id_size, item_id, item_id_size) ;
jack_nframes_t start_frame = strtoul(get_message_part(position, ardourvis::TIME_VALUE_CHARS, msg).c_str(), 0, 10) ;
position += ardourvis::TIME_VALUE_CHARS ;
// get the named time axis
ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_id)) ;
if(!ifta)
{
send_return_failure(std::string("No parent Image Track found: ").append(track_id)) ;
return ;
}
// get the parent scene
ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_id) ;
if(!iftag)
{
send_return_failure(std::string("No parent Scene found: ").append(scene_id)) ;
return ;
}
ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ;
if(!ifv)
{
send_return_failure(std::string("No Image Frame Item found: ").append(item_id)) ;
return ;
}
ifv->set_position(start_frame, this) ;
send_return_success() ;
}
/**
* Handle ImageFrameView Duration changes
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_imageframe_view_duration_update(const char* msg)
{
int position = 6 ; // message type chars
std::string track_id ;
std::string scene_id ;
std::string item_id ;
int track_id_size ;
int scene_id_size ;
int item_id_size ;
this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, scene_id, scene_id_size, item_id, item_id_size) ;
jack_nframes_t duration = strtoul(get_message_part(position,ardourvis::TIME_VALUE_CHARS,msg).c_str(),0,10) ;
position += ardourvis::TIME_VALUE_CHARS ;
// get the named time axis
ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_id)) ;
if(!ifta)
{
send_return_failure(std::string("No parent Image Track found : ").append(track_id)) ;
return ;
}
// get the parent scene
ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_id) ;
if(!iftag)
{
send_return_failure(std::string("No parent Scene found : ").append(scene_id)) ;
return ;
}
ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ;
if(!ifv)
{
send_return_failure(std::string("No Image Frame Item found : ").append(item_id)) ;
return ;
}
ifv->set_duration(duration, this) ;
send_return_success() ;
}
/**
* Handle ImageFrameView Position Lock Constraint changes
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_imageframe_position_lock_update(const char* msg)
{
int position = 6 ; // message type chars
std::string track_id ;
std::string group_id ;
std::string item_id ;
int track_id_size ;
int group_id_size ;
int item_id_size ;
this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
std::string pos_lock = get_message_part(position,1,msg) ;
bool pos_lock_active = false ;
if(pos_lock == "0")
{
pos_lock_active = false ;
}
else if(pos_lock == "1")
{
pos_lock_active = true ;
}
else
{
send_return_failure(std::string("Unknown Value used during Position Loack: ").append(pos_lock)) ;
return ;
}
position += 1 ;
int errcode ;
std::string errmsg ;
ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
if(ifv)
{
ifv->set_position_locked(pos_lock_active, this) ;
send_return_success() ;
}
else
{
send_return_failure(errmsg) ;
}
}
/**
* Handle ImageFrameView Maximum Duration changes
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_imageframe_view_max_duration_update(const char* msg)
{
int position = 6 ; // message type chars
std::string track_id ;
std::string group_id ;
std::string item_id ;
int track_id_size ;
int group_id_size ;
int item_id_size ;
this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
jack_nframes_t max_duration = strtoul(get_message_part(position,ardourvis::TIME_VALUE_CHARS,msg).c_str(),0,10) ;
position += ardourvis::TIME_VALUE_CHARS ;
int errcode ;
std::string errmsg ;
ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
if(ifv)
{
ifv->set_max_duration(max_duration, this) ;
send_return_success() ;
}
else
{
send_return_failure(errmsg) ;
}
}
/**
* Handle image frame max duration enable constraint changes
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_imageframe_view_max_duration_enable_update(const char* msg)
{
int position = 6 ; // message type chars
std::string track_id ;
std::string group_id ;
std::string item_id ;
int track_id_size ;
int group_id_size ;
int item_id_size ;
this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
std::string active = get_message_part(position,1,msg) ;
bool max_duration_active = false ;
if(active == "0")
{
max_duration_active = false ;
}
else if(active == "1")
{
max_duration_active = true ;
}
else
{
send_return_failure(std::string("Unknown Value used during enable max duration: ").append(active)) ;
return ;
}
position += 1 ;
int errcode ;
std::string errmsg ;
ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
if(ifv)
{
ifv->set_max_duration_active(max_duration_active, this) ;
send_return_success() ;
}
else
{
send_return_failure(errmsg) ;
}
}
/**
* Handle ImageFrameView Minimum Duration changes
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_imageframe_view_min_duration_update(const char* msg)
{
int position = 6 ; // message type chars
std::string track_id ;
std::string group_id ;
std::string item_id ;
int track_id_size ;
int group_id_size ;
int item_id_size ;
this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
jack_nframes_t min_duration = strtoul(get_message_part(position,ardourvis::TIME_VALUE_CHARS,msg).c_str(),0,10) ;
position += ardourvis::TIME_VALUE_CHARS ;
int errcode ;
std::string errmsg ;
ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
if(ifv)
{
ifv->set_min_duration(min_duration, this) ;
send_return_success() ;
}
else
{
send_return_failure(errmsg) ;
}
}
/**
* Handle image frame min duration enable constraint changes
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_imageframe_view_min_duration_enable_update(const char* msg)
{
int position = 6 ; // message type chars
std::string track_id ;
std::string group_id ;
std::string item_id ;
int track_id_size ;
int group_id_size ;
int item_id_size ;
this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
std::string active = get_message_part(position,1,msg) ;
bool min_duration_active = false ;
if(active == "0")
{
min_duration_active = false ;
}
else if(active == "1")
{
min_duration_active = true ;
}
else
{
send_return_failure(std::string("Unknown Value used during enable max duration: ").append(active)) ;
return ;
}
position += 1 ;
int errcode ;
std::string errmsg ;
ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
if(ifv)
{
ifv->set_min_duration_active(min_duration_active, this) ;
send_return_success() ;
}
else
{
send_return_failure(errmsg) ;
}
}
/**
* Handle MarkerView position changes
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_marker_view_position_update(const char* msg)
{}
/**
* Handle MarkerView duration changes
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_marker_view_duration_update(const char* msg)
{}
/**
* Handle MarkerView Position Lock Constraint changes
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_marker_view_position_lock_update(const char* msg)
{
}
/**
* Handle MarkerView maximum duration changes
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_marker_view_max_duration_update(const char* msg)
{}
/**
* Handle MarkerView minimum duration changes
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_marker_view_min_duration_update(const char* msg)
{}
//---------------------------------------------------------------------------------------//
// handlers for Session Actions
/**
* Handle the opening of a named audio session
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_open_session(const char* msg)
{
// msg [SAOS][sessionSize][sessionPath]
int position = 4 ; // message type chars
// get the session name size
int session_name_size = atoi(get_message_part(position,3,msg).c_str()) ;
position += 3 ;
// get the session name
std::string session_name = get_message_part(position,session_name_size,msg) ;
position += session_name_size ;
// open the session
std::string path, name ;
bool isnew;
if (ARDOUR::Session::find_session(session_name, path, name, isnew) == 0) {
if (ARDOUR_UI::instance()->load_session (path, name) == 0) {
send_return_success() ;
} else {
std::string retMsg = "Failed to load Session" ;
send_return_failure(retMsg) ;
}
} else {
std::string retMsg = "Failed to find Session" ;
send_return_failure(retMsg) ;
}
}
/**
* Handle the closing of a named audio session
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_closed_session(const char* msg)
{}
//---------------------------------------------------------------------------------------//
// handlers for the shutdown of the Image Compositor
/**
* Handle the shutdown message from the image compositor
*
* @param msg the received message
*/
void
ImageFrameSocketHandler::handle_shutdown(const char* msg)
{
CompositorSocketShutdown() ; /* EMIT_SIGNAL */
}
//---------------------------------------------------------------------------------------//
// convenince methods to break up messages
/**
* Returns part of the received message as a std::string
*
* @param start the start character
* @param num_chars the number of characters to read
* @param the message to break apart
* @return the sub string of the message
*/
std::string
ImageFrameSocketHandler::get_message_part(int start, int32_t num_chars, const char* msg)
{
char buf[num_chars + 1] ;
strncpy(buf,msg+start,num_chars) ;
buf[num_chars] = '\0' ;
std::string s(buf) ;
return(s) ;
}
/**
* break up am image item description message
* we break the mesage up into the parent Image Track id and size,
* the parent group id and size, and the image id and size
*
* @param track_id
* @param track_id_size
* @param scene_id
* @param scene_id_size
* @param item_id
* @param item_id_size
*/
void
ImageFrameSocketHandler::decompose_imageframe_item_desc(const char* msg, int& position, std::string& track_id,
int& track_id_size, std::string& scene_id, int& scene_id_size, std::string& item_id, int& item_id_size)
{
// get the track Id size
track_id_size = atoi(get_message_part(position,ardourvis::TEXT_SIZE_CHARS,msg).c_str()) ;
position += ardourvis::TEXT_SIZE_CHARS ;
// get the track id
track_id = get_message_part(position,track_id_size,msg) ;
position += track_id_size ;
// get the track Id size
scene_id_size = atoi(get_message_part(position,ardourvis::TEXT_SIZE_CHARS,msg).c_str()) ;
position += ardourvis::TEXT_SIZE_CHARS ;
// get the scene id
scene_id = get_message_part(position,scene_id_size,msg) ;
position += scene_id_size ;
// get the item id size
item_id_size = atoi(get_message_part(position,ardourvis::TEXT_SIZE_CHARS,msg).c_str()) ;
position += ardourvis::TEXT_SIZE_CHARS ;
// get the item id
item_id = get_message_part(position,item_id_size,msg) ;
position += item_id_size ;
}
/**
* Compose a description of the specified image frame view
* The description consists of the parent track name size and name,
* the parent group name size and name, and the item name size and name
*
* @param ifv the item to string_compose a description of
* @param buffer the buffer to write the description
*/
void
ImageFrameSocketHandler::compose_imageframe_item_desc(ImageFrameView* ifv, std::ostringstream& buffer)
{
buffer << std::setw(3) << ifv->get_time_axis_group()->get_view().trackview().name().length() ;
buffer << ifv->get_time_axis_group()->get_view().trackview().name() ;
// add the parent scene
buffer << std::setw(3) << ifv->get_time_axis_group()->get_group_name().length() ;
buffer << ifv->get_time_axis_group()->get_group_name() ;
// add the ImageFrameItem id length and Id
buffer << setw(3) << ifv->get_item_name().length() ;
buffer << ifv->get_item_name() ;
}
/**
* Compose a description of the specified marker view
* The description consists of the parent track name size and name,
* and the item name size and name
*
* @param mv the item to string_compose a description of
* @param buffer the buffer to write the description
*/
void
ImageFrameSocketHandler::compose_marker_item_desc(MarkerView* mv, std::ostringstream& buffer)
{
MarkerTimeAxis* mta = dynamic_cast<MarkerTimeAxis*>(&mv->get_time_axis_view()) ;
if(!mta)
{
return ;
}
buffer << std::setw(3) << mta->name().length() ;
buffer << mta->name() ;
buffer << std::setw(3) << mv->get_item_name().length() ;
buffer << mv->get_item_name() ;
}
/**
* Returns the ImageFrameView from the specified description
* The errcode parameter is used to indicate the item which caused
* an error on failure of this method
* 0 = success
* 1 = the track item was not found
* 2 = the group item was not found
* 3 = the imageframe item was not found
*
* @paran track_id the track on which the item is placed
* @param group_id the group in which the item is a member
* @param item_id the id of the item
* @param int32_t reference used for error codes on failure
* @param errmsg populated with a description of the error on failure
* @return the described item on success, 0 otherwise
*/
ImageFrameView*
ImageFrameSocketHandler::get_imageframe_view_from_desc(const string & track_id, const string & group_id, const string & item_id, int& errcode, std::string& errmsg)
{
ImageFrameView* item = 0 ;
// get the named time axis
ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_id)) ;
if(!ifta)
{
errcode = 1 ;
errmsg = std::string("Image Frame Time Axis Not Found: ").append(track_id) ;
}
else
{
// get the parent scene
ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(group_id) ;
if(!iftag)
{
errcode = 2 ;
errmsg = std::string("Image Frame Group Not Found: ").append(group_id) ;
}
else
{
ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ;
if(!ifv)
{
errcode = 3 ;
errmsg = std::string("Image Frame Item Not Found: ").append(item_id) ;
}
else
{
// yay!!
item = ifv ;
errcode = 0 ;
}
}
}
return(item) ;
}
//---------------------------------------------------------------------------------------//
// Convenince Message Send Methods
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
/**
* Sends a message throught the socket
*
* @param msg the message to send
* @return the return value of the socket call
*/
int
ImageFrameSocketHandler::send_message(const string & msg)
{
//std::cout << "Sending Message [" << msg << "]\n" ;
int retcode = ::send(theArdourToCompositorSocket, msg.c_str(), msg.length(), MSG_NOSIGNAL) ;
return(retcode) ;
}
/**
* Reads a message from the Socket
*
* @param msg a string to populate with the received message
* @return the return value from the socket call
*/
int
ImageFrameSocketHandler::read_message(std::string& msg)
{
char buf[ardourvis::MAX_MSG_SIZE + 1] ;
memset(buf, 0, (ardourvis::MAX_MSG_SIZE + 1)) ;
msg = "" ;
int retcode = ::recv(theArdourToCompositorSocket, buf, ardourvis::MAX_MSG_SIZE, 0) ;
msg = buf ;
//std::cout << "Received Message [" << msg << "]\n" ;
return(retcode) ;
}
/**
* Convenience method to string_compose and send a success messasge back to the Image Compositor
*
*/
void
ImageFrameSocketHandler::send_return_success()
{
send_message(ardourvis::RETURN_TRUE) ;
}
/**
* Convenience method to string_compose and send a failure messasge back to the Image Compositor
*
* @param msg the failure message
*/
void
ImageFrameSocketHandler::send_return_failure(const std::string& msg)
{
std::ostringstream buf ;
buf << std::setfill('0') ;
buf << ardourvis::RETURN_FALSE ;
buf << std::setw(3) << msg.length(); ;
buf << msg ;
send_message(buf.str()) ;
}