Jack2 1.9.6

JackMachClientChannel.cpp

00001 /*
00002 Copyright (C) 2004-2008 Grame
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU Lesser General Public License as published by
00006 the Free Software Foundation; either version 2.1 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public License
00015 along with this program; if not, write to the Free Software 
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 
00018 */
00019 
00020 #include "JackMachClientChannel.h"
00021 #include "JackRPCEngine.h"
00022 #include "JackTools.h"
00023 #include "JackRPCClientServer.c"
00024 #include "JackError.h"
00025 #include "JackLibClient.h"
00026 #include "JackMachThread.h"
00027 #include "JackConstants.h"
00028 
00029 namespace Jack
00030 {
00031 
00032 std::map<mach_port_t, JackClient*> gClientTable;
00033 
00034 JackMachClientChannel::JackMachClientChannel():fPrivatePort(0),fThread(this)
00035 {}
00036 
00037 JackMachClientChannel::~JackMachClientChannel()
00038 {}
00039 
00040 // Server <===> client
00041 
00042 int JackMachClientChannel::ServerCheck(const char* server_name)
00043 {
00044     jack_log("JackMachClientChannel::ServerCheck = %s", server_name);
00045     char jack_server_entry_name[512];
00046     snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s.%d_%s", jack_server_entry, JackTools::GetUID(), server_name);
00047 
00048     // Connect to server
00049     if (!fServerPort.ConnectPort(jack_server_entry_name)) {
00050         jack_error("Cannot connect to server Mach port");
00051         return -1;
00052     } else {
00053         return 0;
00054     }
00055 }
00056 
00057 int JackMachClientChannel::Open(const char* server_name, const char* name, char* name_res, JackClient* client, jack_options_t options, jack_status_t* status)
00058 {
00059     jack_log("JackMachClientChannel::Open name = %s", name);
00060     char jack_server_entry_name[512];
00061     snprintf(jack_server_entry_name, sizeof(jack_server_entry_name), "%s.%d_%s", jack_server_entry, JackTools::GetUID(), server_name);
00062 
00063     // Connect to server
00064     if (!fServerPort.ConnectPort(jack_server_entry_name)) {
00065         jack_error("Cannot connect to server Mach port");
00066         return -1;
00067     }
00068 
00069     // Check name in server
00070     int result = 0;
00071     ClientCheck(name, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result);
00072     if (result < 0) {
00073         int status1 = *status;
00074         if (status1 & JackVersionError)
00075             jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION);
00076         else
00077             jack_error("Client name = %s conflits with another running client", name);
00078         return -1;
00079     }
00080 
00081     // Prepare local port using client name
00082     char buf[JACK_CLIENT_NAME_SIZE + 1];
00083     snprintf(buf, sizeof(buf) - 1, "%s:%s", jack_client_entry, name_res);
00084 
00085     if (!fClientPort.AllocatePort(buf, 16)) {
00086         jack_error("Cannot allocate client Mach port");
00087         return -1;
00088     }
00089 
00090     gClientTable[fClientPort.GetPort()] = client;
00091     return 0;
00092 }
00093 
00094 void JackMachClientChannel::Close()
00095 {
00096     jack_log("JackMachClientChannel::Close");
00097     gClientTable.erase(fClientPort.GetPort());
00098     fServerPort.DisconnectPort();
00099     fClientPort.DestroyPort();
00100 
00101     if (fPrivatePort != 0) {
00102          kern_return_t res;
00103         if ((res = mach_port_destroy(mach_task_self(), fPrivatePort)) != KERN_SUCCESS) {
00104             jack_error("JackMachClientChannel::Close err = %s", mach_error_string(res));
00105         }
00106     }
00107 }
00108 
00109 int JackMachClientChannel::Start()
00110 {
00111     jack_log("JackMachClientChannel::Start");
00112     /*
00113      To be sure notification thread is started before ClientOpen is called.
00114     */
00115     if (fThread.StartSync() != 0) {
00116         jack_error("Cannot start Jack client listener");
00117         return -1;
00118     } else {
00119         return 0;
00120     }
00121 }
00122 
00123 void JackMachClientChannel::Stop()
00124 {
00125     jack_log("JackMachClientChannel::Stop");
00126     fThread.Kill();
00127 }
00128 
00129 void JackMachClientChannel::ClientCheck(const char* name, char* name_res, int protocol, int options, int* status, int* result)
00130 {
00131     kern_return_t res = rpc_jack_client_check(fServerPort.GetPort(), (char*)name, name_res, protocol, options, status, result);
00132     if (res != KERN_SUCCESS) {
00133         *result = -1;
00134         jack_error("JackMachClientChannel::ClientCheck err = %s", mach_error_string(res));
00135     }
00136 }
00137 
00138 void JackMachClientChannel::ClientOpen(const char* name, int pid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
00139 {
00140     kern_return_t res = rpc_jack_client_open(fServerPort.GetPort(), (char*)name, pid, &fPrivatePort, shared_engine, shared_client, shared_graph, result);
00141     if (res != KERN_SUCCESS) {
00142         *result = -1;
00143         jack_error("JackMachClientChannel::ClientOpen err = %s", mach_error_string(res));
00144     }
00145 }
00146 
00147 void JackMachClientChannel::ClientClose(int refnum, int* result)
00148 {
00149     kern_return_t res = rpc_jack_client_close(fPrivatePort, refnum, result);
00150     if (res != KERN_SUCCESS) {
00151         *result = -1;
00152         jack_error("JackMachClientChannel::ClientClose err = %s", mach_error_string(res));
00153     }
00154 }
00155 
00156 void JackMachClientChannel::ClientActivate(int refnum, int is_real_time, int* result)
00157 {
00158     kern_return_t res = rpc_jack_client_activate(fPrivatePort, refnum, is_real_time, result);
00159     if (res != KERN_SUCCESS) {
00160         *result = -1;
00161         jack_error("JackMachClientChannel::ClientActivate err = %s", mach_error_string(res));
00162     }
00163 }
00164 
00165 void JackMachClientChannel::ClientDeactivate(int refnum, int* result)
00166 {
00167     kern_return_t res = rpc_jack_client_deactivate(fPrivatePort, refnum, result);
00168     if (res != KERN_SUCCESS) {
00169         *result = -1;
00170         jack_error("JackMachClientChannel::ClientDeactivate err = %s", mach_error_string(res));
00171     }
00172 }
00173 
00174 void JackMachClientChannel::PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result)
00175 {
00176     kern_return_t res = rpc_jack_port_register(fPrivatePort, refnum, (char*)name, (char*)type, flags, buffer_size, port_index, result);
00177     if (res != KERN_SUCCESS) {
00178         *result = -1;
00179         jack_error("JackMachClientChannel::PortRegister err = %s", mach_error_string(res));
00180     }
00181 }
00182 
00183 void JackMachClientChannel::PortUnRegister(int refnum, jack_port_id_t port_index, int* result)
00184 {
00185     kern_return_t res = rpc_jack_port_unregister(fPrivatePort, refnum, port_index, result);
00186     if (res != KERN_SUCCESS) {
00187         *result = -1;
00188         jack_error("JackMachClientChannel::PortUnRegister err = %s", mach_error_string(res));
00189     }
00190 }
00191 
00192 void JackMachClientChannel::PortConnect(int refnum, const char* src, const char* dst, int* result)
00193 {
00194     kern_return_t res = rpc_jack_port_connect_name(fPrivatePort, refnum, (char*)src, (char*)dst, result);
00195     if (res != KERN_SUCCESS) {
00196         jack_error("JackMachClientChannel::PortConnect err = %s", mach_error_string(res));
00197     }
00198 }
00199 
00200 void JackMachClientChannel::PortDisconnect(int refnum, const char* src, const char* dst, int* result)
00201 {
00202     kern_return_t res = rpc_jack_port_disconnect_name(fPrivatePort, refnum, (char*)src, (char*)dst, result);
00203     if (res != KERN_SUCCESS) {
00204         *result = -1;
00205         jack_error("JackMachClientChannel::PortDisconnect err = %s", mach_error_string(res));
00206     }
00207 }
00208 
00209 void JackMachClientChannel::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result)
00210 {
00211     kern_return_t res = rpc_jack_port_connect(fPrivatePort, refnum, src, dst, result);
00212     if (res != KERN_SUCCESS) {
00213         *result = -1;
00214         jack_error("JackMachClientChannel::PortConnect err = %s", mach_error_string(res));
00215     }
00216 }
00217 
00218 void JackMachClientChannel::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result)
00219 {
00220     kern_return_t res = rpc_jack_port_disconnect(fPrivatePort, refnum, src, dst, result);
00221     if (res != KERN_SUCCESS) {
00222         *result = -1;
00223         jack_error("JackMachClientChannel::PortDisconnect err = %s", mach_error_string(res));
00224     }
00225 }
00226 
00227 void JackMachClientChannel::PortRename(int refnum, jack_port_id_t port, const char* name, int* result)
00228 {
00229     kern_return_t res = rpc_jack_port_rename(fPrivatePort, refnum, port, (char*)name, result);
00230     if (res != KERN_SUCCESS) {
00231         *result = -1;
00232         jack_error("JackMachClientChannel::PortRename err = %s", mach_error_string(res));
00233     }
00234 }
00235 
00236 void JackMachClientChannel::SetBufferSize(jack_nframes_t buffer_size, int* result)
00237 {
00238     kern_return_t res = rpc_jack_set_buffer_size(fPrivatePort, buffer_size, result);
00239     if (res != KERN_SUCCESS) {
00240         *result = -1;
00241         jack_error("JackMachClientChannel::SetBufferSize err = %s", mach_error_string(res));
00242     }
00243 }
00244 
00245 void JackMachClientChannel::SetFreewheel(int onoff, int* result)
00246 {
00247     kern_return_t res = rpc_jack_set_freewheel(fPrivatePort, onoff, result);
00248     if (res != KERN_SUCCESS) {
00249         *result = -1;
00250         jack_error("JackMachClientChannel::SetFreewheel err = %s", mach_error_string(res));
00251     }
00252 }
00253 
00254 void JackMachClientChannel::ReleaseTimebase(int refnum, int* result)
00255 {
00256     kern_return_t res = rpc_jack_release_timebase(fPrivatePort, refnum, result);
00257     if (res != KERN_SUCCESS) {
00258         *result = -1;
00259         jack_error("JackMachClientChannel::ReleaseTimebase err = %s", mach_error_string(res));
00260     }
00261 }
00262 
00263 void JackMachClientChannel::SetTimebaseCallback(int refnum, int conditional, int* result)
00264 {
00265     kern_return_t res = rpc_jack_set_timebase_callback(fPrivatePort, refnum, conditional, result);
00266     if (res != KERN_SUCCESS) {
00267         *result = -1;
00268         jack_error("JackMachClientChannel::SetTimebaseCallback err = %s", mach_error_string(res));
00269     }
00270 }
00271 
00272 void JackMachClientChannel::GetInternalClientName(int refnum, int int_ref, char* name_res, int* result)
00273 {
00274     kern_return_t res = rpc_jack_get_internal_clientname(fPrivatePort, refnum, int_ref, name_res, result);
00275     if (res != KERN_SUCCESS) {
00276         *result = -1;
00277         jack_error("JackMachClientChannel::GetInternalClientName err = %s", mach_error_string(res));
00278     }
00279 }
00280 
00281 void JackMachClientChannel::InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result)
00282 {
00283     kern_return_t res = rpc_jack_internal_clienthandle(fPrivatePort, refnum, (char*)client_name, status, int_ref, result);
00284     if (res != KERN_SUCCESS) {
00285         *result = -1;
00286         jack_error("JackMachClientChannel::InternalClientHandle err = %s", mach_error_string(res));
00287     }
00288 }
00289 
00290 void JackMachClientChannel::InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int* result)
00291 {
00292     const char* int_client_name = (client_name) ? client_name : "";
00293     const char* int_so_name = (so_name) ? so_name : "";
00294     const char* int_objet_data = (objet_data) ? objet_data : "";
00295     
00296     kern_return_t res = rpc_jack_internal_clientload(fPrivatePort, refnum, (char*)int_client_name, (char*)int_so_name, (char*)int_objet_data, options, status, int_ref, result);
00297     if (res != KERN_SUCCESS) {
00298         *result = -1;
00299         jack_error("JackMachClientChannel::InternalClientLoad err = %s", mach_error_string(res));
00300     }
00301 }
00302 
00303 void JackMachClientChannel::InternalClientUnload(int refnum, int int_ref, int* status, int* result)
00304 {
00305     kern_return_t res = rpc_jack_internal_clientunload(fPrivatePort, refnum, int_ref, status, result);
00306     if (res != KERN_SUCCESS) {
00307         *result = -1;
00308         jack_error("JackMachClientChannel::InternalClientUnload err = %s", mach_error_string(res));
00309     }
00310 }
00311 
00312 bool JackMachClientChannel::Init()
00313 {
00314     jack_log("JackMachClientChannel::Init");
00315     JackClient* client = gClientTable[fClientPort.GetPort()];
00316     return client->Init();
00317 }
00318 
00319 bool JackMachClientChannel::Execute()
00320 {
00321     kern_return_t res;
00322     if ((res = mach_msg_server(JackRPCClient_server, 1024, fClientPort.GetPort(), 0)) != KERN_SUCCESS) {
00323         jack_error("JackMachClientChannel::Execute err = %s", mach_error_string(res));
00324         JackClient* client = gClientTable[fClientPort.GetPort()];
00325         client->ShutDown();
00326         return false;
00327     } else {
00328         return true;
00329     }
00330 }
00331 
00332 } // end of namespace
00333 
00334