Jack2 1.9.6
|
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 "JackTools.h" 00021 #include "JackMachServerChannel.h" 00022 #include "JackRPCEngineServer.c" 00023 #include "JackError.h" 00024 #include "JackServer.h" 00025 #include "JackLockedEngine.h" 00026 #include "JackNotification.h" 00027 #include "JackServerGlobals.h" 00028 00029 using namespace std; 00030 00031 namespace Jack 00032 { 00033 00034 map<mach_port_t, JackMachServerChannel*> JackMachServerChannel::fPortTable; 00035 00036 JackMachServerChannel::JackMachServerChannel():fThread(this) 00037 {} 00038 00039 JackMachServerChannel::~JackMachServerChannel() 00040 {} 00041 00042 int JackMachServerChannel::Open(const char* server_name, JackServer* server) 00043 { 00044 jack_log("JackMachServerChannel::Open"); 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 if (!fServerPort.AllocatePort(jack_server_entry_name, 16)) { // 16 is the max possible value 00049 jack_error("Cannot check in Jack server"); 00050 return -1; 00051 } 00052 00053 fServer = server; 00054 fPortTable[fServerPort.GetPort()] = this; 00055 return 0; 00056 } 00057 00058 void JackMachServerChannel::Close() 00059 { 00060 jack_log("JackMachServerChannel::Close"); 00061 #ifdef MAC_OS_X_VERSION_10_5 00062 // Exception does not work in this case on pre Snow Loopard systems, see JackMachServerNotifyChannel::NotifyQuit() 00063 fThread.Kill(); 00064 #else 00065 fThread.Stop(); 00066 #endif 00067 fServerPort.DestroyPort(); 00068 } 00069 00070 int JackMachServerChannel::Start() 00071 { 00072 if (fThread.Start() != 0) { 00073 jack_error("Cannot start Jack server listener"); 00074 return -1; 00075 } 00076 00077 return 0; 00078 } 00079 00080 JackLockedEngine* JackMachServerChannel::GetEngine() 00081 { 00082 return fServer->GetEngine(); 00083 } 00084 00085 JackServer* JackMachServerChannel::GetServer() 00086 { 00087 return fServer; 00088 } 00089 00090 void JackMachServerChannel::ClientCheck(char* name, char* name_res, int protocol, int options, int* status, int* result) 00091 { 00092 *result = GetEngine()->ClientCheck(name, name_res, protocol, options, status); 00093 } 00094 00095 void JackMachServerChannel::ClientOpen(char* name, int pid, mach_port_t* private_port, int* shared_engine, int* shared_client, int* shared_graph, int* result) 00096 { 00097 int refnum = -1; 00098 *result = GetEngine()->ClientExternalOpen(name, pid, &refnum, shared_engine, shared_client, shared_graph); 00099 00100 if (*result == 0) { 00101 mach_port_t port = fServerPort.AddPort(); 00102 if (port != 0) { 00103 fClientTable[port] = refnum; 00104 fPortTable[port] = this; 00105 *private_port = port; 00106 } else { 00107 jack_error("Cannot create private client mach port"); 00108 *result = -1; 00109 } 00110 } else { 00111 jack_error("Cannot create new client"); 00112 } 00113 } 00114 00115 void JackMachServerChannel::ClientClose(mach_port_t private_port, int refnum) 00116 { 00117 GetEngine()->ClientExternalClose(refnum); 00118 fClientTable.erase(private_port); 00119 00120 // Hum, hum.... 00121 kern_return_t res; 00122 if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) { 00123 jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res)); 00124 } 00125 } 00126 00127 void JackMachServerChannel::ClientKill(mach_port_t private_port) 00128 { 00129 jack_log("JackMachServerChannel::ClientKill"); 00130 int refnum = fClientTable[private_port]; 00131 assert(refnum > 0); 00132 fServer->ClientKill(refnum); 00133 fClientTable.erase(private_port); 00134 00135 // Hum, hum.... 00136 kern_return_t res; 00137 if ((res = mach_port_destroy(mach_task_self(), private_port)) != KERN_SUCCESS) { 00138 jack_error("server_rpc_jack_client_close mach_port_destroy %s", mach_error_string(res)); 00139 } 00140 } 00141 00142 boolean_t JackMachServerChannel::MessageHandler(mach_msg_header_t* Request, mach_msg_header_t* Reply) 00143 { 00144 if (Request->msgh_id == MACH_NOTIFY_NO_SENDERS) { 00145 jack_log("MACH_NOTIFY_NO_SENDERS %ld", Request->msgh_local_port); 00146 JackMachServerChannel* channel = JackMachServerChannel::fPortTable[Request->msgh_local_port]; 00147 assert(channel); 00148 channel->ClientKill(Request->msgh_local_port); 00149 } else { 00150 JackRPCEngine_server(Request, Reply); 00151 } 00152 return true; 00153 } 00154 00155 bool JackMachServerChannel::Execute() 00156 { 00157 try { 00158 00159 kern_return_t res; 00160 if ((res = mach_msg_server(MessageHandler, 1024, fServerPort.GetPortSet(), 0)) != KERN_SUCCESS) { 00161 jack_log("JackMachServerChannel::Execute: err = %s", mach_error_string(res)); 00162 // A recoverable error, so keep running... 00163 } 00164 return true; 00165 00166 } catch (JackQuitException& e) { 00167 jack_log("JackMachServerChannel::Execute JackQuitException"); 00168 return false; 00169 } 00170 } 00171 00172 } // end of namespace 00173 00174