1 /* 2 * Copyright (c) 1999-2000, Eric Moon. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions, and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32 #include "AddOnHost.h" 33 #include "AddOnHostProtocol.h" 34 35 #include <Application.h> 36 #include <Debug.h> 37 #include <Entry.h> 38 #include <MediaNode.h> 39 #include <MediaRoster.h> 40 #include <Messenger.h> 41 #include <Path.h> 42 #include <Roster.h> 43 44 #include <OS.h> 45 46 #include <cstdlib> 47 #include <cstring> 48 49 __USE_CORTEX_NAMESPACE 50 51 // -------------------------------------------------------- // 52 // constants 53 // -------------------------------------------------------- // 54 55 BMessenger AddOnHost::s_messenger; 56 57 // -------------------------------------------------------- // 58 // *** static interface 59 // -------------------------------------------------------- // 60 61 /*static*/ 62 status_t AddOnHost::FindInstance( 63 BMessenger* outMessenger) { 64 65 status_t err; 66 67 // no current app? launch one 68 if(!s_messenger.IsValid()) { 69 s_messenger = BMessenger( 70 addon_host::g_appSignature, 71 -1, 72 &err); 73 74 if(err < B_OK) 75 return err; 76 if(!s_messenger.IsValid()) 77 return B_ERROR; 78 } 79 80 *outMessenger = s_messenger; 81 return B_OK; 82 } 83 84 /*static*/ 85 status_t AddOnHost::Kill( 86 bigtime_t timeout) { 87 88 if(!s_messenger.IsValid()) 89 return B_NOT_ALLOWED; 90 91 status_t err = kill_team(s_messenger.Team()); 92 return err; 93 } 94 95 /*static*/ 96 status_t AddOnHost::Launch( 97 BMessenger* outMessenger) { 98 99 if(s_messenger.IsValid()) 100 return B_NOT_ALLOWED; 101 102 status_t err; 103 104 // find it 105 entry_ref appRef; 106 err = be_roster->FindApp(addon_host::g_appSignature, &appRef); 107 if(err < B_OK) 108 return err; 109 110 // start it 111 team_id team; 112 const char* arg = "--addon-host"; 113 err = be_roster->Launch( 114 &appRef, 115 1, 116 &arg, 117 &team); 118 if(err < B_OK) 119 return err; 120 121 // fetch messenger to the new app and return it 122 s_messenger = BMessenger( 123 addon_host::g_appSignature, 124 team, 125 &err); 126 127 if(err < B_OK) 128 return err; 129 if(!s_messenger.IsValid()) 130 return B_ERROR; 131 132 if(outMessenger) 133 *outMessenger = s_messenger; 134 135 return B_OK; 136 } 137 138 /*static*/ 139 status_t AddOnHost::InstantiateDormantNode( 140 const dormant_node_info& info, 141 media_node* outNode, 142 bigtime_t timeout) { 143 144 status_t err; 145 146 if(!s_messenger.IsValid()) { 147 err = Launch(0); 148 149 if(err < B_OK) { 150 // give up 151 PRINT(( 152 "!!! AddOnHost::InstantiateDormantNode(): Launch() failed:\n" 153 " %s\n", 154 strerror(err))); 155 return err; 156 } 157 } 158 159 // do it 160 ASSERT(s_messenger.IsValid()); 161 BMessage request(addon_host::M_INSTANTIATE); 162 request.AddData("info", B_RAW_TYPE, &info, sizeof(dormant_node_info)); 163 164 BMessage reply(B_NO_REPLY); 165 err = s_messenger.SendMessage( 166 &request, 167 &reply, 168 timeout, 169 timeout); 170 171 // PRINT(( 172 // "### SendMessage() returned '%s'\n", strerror(err))); 173 174 if(err < B_OK) { 175 PRINT(( 176 "!!! AddOnHost::InstantiateDormantNode(): SendMessage() failed:\n" 177 " %s\n", 178 strerror(err))); 179 return err; 180 } 181 182 if(reply.what == B_NO_REPLY) { 183 PRINT(( 184 "!!! AddOnHost::InstantiateDormantNode(): no reply.\n")); 185 return B_ERROR; 186 } 187 188 if(reply.what == addon_host::M_INSTANTIATE_COMPLETE) { 189 media_node_id nodeID; 190 191 // fetch node ID 192 err = reply.FindInt32("node_id", &nodeID); 193 if(err < B_OK) { 194 PRINT(( 195 "!!! AddOnHost::InstantiateDormantNode(): 'node_id' missing from reply.\n")); 196 return B_ERROR; 197 } 198 199 // fetch node 200 err = BMediaRoster::Roster()->GetNodeFor(nodeID, outNode); 201 if(err < B_OK) { 202 PRINT(( 203 "!!! AddOnHost::InstantiateDormantNode(): node missing!\n")); 204 return B_ERROR; 205 } 206 207 // // now solely owned by the add-on host team 208 // BMediaRoster::Roster()->ReleaseNode(*outNode); 209 210 return B_OK; 211 } 212 213 // failed: 214 return (reply.FindInt32("error", &err) == B_OK) ? err : B_ERROR; 215 } 216 217 /*static*/ 218 status_t AddOnHost::ReleaseInternalNode( 219 const live_node_info& info, 220 bigtime_t timeout) { 221 222 status_t err; 223 224 if(!s_messenger.IsValid()) { 225 err = Launch(0); 226 227 if(err < B_OK) { 228 // give up 229 PRINT(( 230 "!!! AddOnHost::ReleaseInternalNode(): Launch() failed:\n" 231 " %s\n", 232 strerror(err))); 233 return err; 234 } 235 } 236 237 // do it 238 ASSERT(s_messenger.IsValid()); 239 BMessage request(addon_host::M_RELEASE); 240 request.AddData("info", B_RAW_TYPE, &info, sizeof(live_node_info)); 241 242 BMessage reply(B_NO_REPLY); 243 err = s_messenger.SendMessage( 244 &request, 245 &reply, 246 timeout, 247 timeout); 248 249 250 if(err < B_OK) { 251 PRINT(( 252 "!!! AddOnHost::ReleaseInternalNode(): SendMessage() failed:\n" 253 " %s\n", 254 strerror(err))); 255 return err; 256 } 257 258 if(reply.what == B_NO_REPLY) { 259 PRINT(( 260 "!!! AddOnHost::InstantiateDormantNode(): no reply.\n")); 261 return B_ERROR; 262 } 263 264 if(reply.what == addon_host::M_RELEASE_COMPLETE) { 265 return B_OK; 266 } 267 268 // failed: 269 return (reply.FindInt32("error", &err) == B_OK) ? err : B_ERROR; 270 } 271 272