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