1 // AddOnHost.cpp 2 3 #include "AddOnHost.h" 4 #include "AddOnHostProtocol.h" 5 6 #include <Application.h> 7 #include <Debug.h> 8 #include <Entry.h> 9 #include <MediaNode.h> 10 #include <MediaRoster.h> 11 #include <Messenger.h> 12 #include <Path.h> 13 #include <Roster.h> 14 15 #include <OS.h> 16 17 #include <cstdlib> 18 #include <cstring> 19 20 __USE_CORTEX_NAMESPACE 21 22 // -------------------------------------------------------- // 23 // constants 24 // -------------------------------------------------------- // 25 26 BMessenger AddOnHost::s_messenger; 27 28 // -------------------------------------------------------- // 29 // *** static interface 30 // -------------------------------------------------------- // 31 32 /*static*/ 33 status_t AddOnHost::FindInstance( 34 BMessenger* outMessenger) { 35 36 status_t err; 37 38 // no current app? launch one 39 if(!s_messenger.IsValid()) { 40 s_messenger = BMessenger( 41 addon_host::g_appSignature, 42 -1, 43 &err); 44 45 if(err < B_OK) 46 return err; 47 if(!s_messenger.IsValid()) 48 return B_ERROR; 49 } 50 51 *outMessenger = s_messenger; 52 return B_OK; 53 } 54 55 /*static*/ 56 status_t AddOnHost::Kill( 57 bigtime_t timeout) { 58 59 if(!s_messenger.IsValid()) 60 return B_NOT_ALLOWED; 61 62 status_t err = kill_team(s_messenger.Team()); 63 return err; 64 } 65 66 /*static*/ 67 status_t AddOnHost::Launch( 68 BMessenger* outMessenger) { 69 70 if(s_messenger.IsValid()) 71 return B_NOT_ALLOWED; 72 73 status_t err; 74 75 // find it 76 entry_ref appRef; 77 err = be_roster->FindApp(addon_host::g_appSignature, &appRef); 78 if(err < B_OK) 79 return err; 80 81 // start it 82 team_id team; 83 const char* arg = "--addon-host"; 84 err = be_roster->Launch( 85 &appRef, 86 1, 87 &arg, 88 &team); 89 if(err < B_OK) 90 return err; 91 92 // fetch messenger to the new app and return it 93 s_messenger = BMessenger( 94 addon_host::g_appSignature, 95 team, 96 &err); 97 98 if(err < B_OK) 99 return err; 100 if(!s_messenger.IsValid()) 101 return B_ERROR; 102 103 if(outMessenger) 104 *outMessenger = s_messenger; 105 106 return B_OK; 107 } 108 109 /*static*/ 110 status_t AddOnHost::InstantiateDormantNode( 111 const dormant_node_info& info, 112 media_node* outNode, 113 bigtime_t timeout) { 114 115 status_t err; 116 117 if(!s_messenger.IsValid()) { 118 err = Launch(0); 119 120 if(err < B_OK) { 121 // give up 122 PRINT(( 123 "!!! AddOnHost::InstantiateDormantNode(): Launch() failed:\n" 124 " %s\n", 125 strerror(err))); 126 return err; 127 } 128 } 129 130 // do it 131 ASSERT(s_messenger.IsValid()); 132 BMessage request(addon_host::M_INSTANTIATE); 133 request.AddData("info", B_RAW_TYPE, &info, sizeof(dormant_node_info)); 134 135 BMessage reply(B_NO_REPLY); 136 err = s_messenger.SendMessage( 137 &request, 138 &reply, 139 timeout, 140 timeout); 141 142 // PRINT(( 143 // "### SendMessage() returned '%s'\n", strerror(err))); 144 145 if(err < B_OK) { 146 PRINT(( 147 "!!! AddOnHost::InstantiateDormantNode(): SendMessage() failed:\n" 148 " %s\n", 149 strerror(err))); 150 return err; 151 } 152 153 if(reply.what == B_NO_REPLY) { 154 PRINT(( 155 "!!! AddOnHost::InstantiateDormantNode(): no reply.\n")); 156 return B_ERROR; 157 } 158 159 if(reply.what == addon_host::M_INSTANTIATE_COMPLETE) { 160 media_node_id nodeID; 161 162 // fetch node ID 163 err = reply.FindInt32("node_id", &nodeID); 164 if(err < B_OK) { 165 PRINT(( 166 "!!! AddOnHost::InstantiateDormantNode(): 'node_id' missing from reply.\n")); 167 return B_ERROR; 168 } 169 170 // fetch node 171 err = BMediaRoster::Roster()->GetNodeFor(nodeID, outNode); 172 if(err < B_OK) { 173 PRINT(( 174 "!!! AddOnHost::InstantiateDormantNode(): node missing!\n")); 175 return B_ERROR; 176 } 177 178 // // now solely owned by the add-on host team 179 // BMediaRoster::Roster()->ReleaseNode(*outNode); 180 181 return B_OK; 182 } 183 184 // failed: 185 return (reply.FindInt32("error", &err) == B_OK) ? err : B_ERROR; 186 } 187 188 /*static*/ 189 status_t AddOnHost::ReleaseInternalNode( 190 const live_node_info& info, 191 bigtime_t timeout) { 192 193 status_t err; 194 195 if(!s_messenger.IsValid()) { 196 err = Launch(0); 197 198 if(err < B_OK) { 199 // give up 200 PRINT(( 201 "!!! AddOnHost::ReleaseInternalNode(): Launch() failed:\n" 202 " %s\n", 203 strerror(err))); 204 return err; 205 } 206 } 207 208 // do it 209 ASSERT(s_messenger.IsValid()); 210 BMessage request(addon_host::M_RELEASE); 211 request.AddData("info", B_RAW_TYPE, &info, sizeof(live_node_info)); 212 213 BMessage reply(B_NO_REPLY); 214 err = s_messenger.SendMessage( 215 &request, 216 &reply, 217 timeout, 218 timeout); 219 220 221 if(err < B_OK) { 222 PRINT(( 223 "!!! AddOnHost::ReleaseInternalNode(): SendMessage() failed:\n" 224 " %s\n", 225 strerror(err))); 226 return err; 227 } 228 229 if(reply.what == B_NO_REPLY) { 230 PRINT(( 231 "!!! AddOnHost::InstantiateDormantNode(): no reply.\n")); 232 return B_ERROR; 233 } 234 235 if(reply.what == addon_host::M_RELEASE_COMPLETE) { 236 return B_OK; 237 } 238 239 // failed: 240 return (reply.FindInt32("error", &err) == B_OK) ? err : B_ERROR; 241 } 242 243 // END -- AddOnHost.cpp --