1/* 2 * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files or portions 6 * thereof (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, merge, 8 * publish, distribute, sublicense, and/or sell copies of the Software, 9 * and to permit persons to whom the Software is furnished to do so, subject 10 * to the following conditions: 11 * 12 * * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * * Redistributions in binary form must reproduce the above copyright notice 16 * in the binary, as well as this list of conditions and the following 17 * disclaimer in the documentation and/or other materials provided with 18 * the distribution. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 * THE SOFTWARE. 27 * 28 */ 29 30 31#include "AppManager.h" 32 33#include <stdio.h> 34 35#include <Application.h> 36#include <Autolock.h> 37#include <OS.h> 38#include <Roster.h> 39 40#include <debug.h> 41#include <MediaMisc.h> 42 43#include "BufferManager.h" 44#include "media_server.h" 45#include "NodeManager.h" 46#include "NotificationManager.h" 47 48 49AppManager::AppManager() 50 : 51 BLocker("media app manager") 52{ 53 fQuit = create_sem(0, "big brother waits"); 54 fBigBrother = spawn_thread(_BigBrotherEntry, "big brother is watching you", 55 B_NORMAL_PRIORITY, this); 56 resume_thread(fBigBrother); 57} 58 59 60AppManager::~AppManager() 61{ 62 delete_sem(fQuit); 63 wait_for_thread(fBigBrother, NULL); 64} 65 66 67bool 68AppManager::HasTeam(team_id team) 69{ 70 BAutolock lock(this); 71 return fMap.find(team) != fMap.end(); 72} 73 74 75status_t 76AppManager::RegisterTeam(team_id team, const BMessenger& messenger) 77{ 78 BAutolock lock(this); 79 80 TRACE("AppManager::RegisterTeam %ld\n", team); 81 if (HasTeam(team)) { 82 ERROR("AppManager::RegisterTeam: team %ld already registered\n", team); 83 return B_ERROR; 84 } 85 86 try { 87 fMap.insert(std::make_pair(team, messenger)); 88 } catch (std::bad_alloc& exception) { 89 return B_NO_MEMORY; 90 } 91 92 return B_OK; 93} 94 95 96status_t 97AppManager::UnregisterTeam(team_id team) 98{ 99 TRACE("AppManager::UnregisterTeam %ld\n", team); 100 101 Lock(); 102 bool isRemoved = fMap.erase(team) != 0; 103 Unlock(); 104 105 _CleanupTeam(team); 106 107 return isRemoved ? B_OK : B_ERROR; 108} 109 110 111team_id 112AppManager::AddOnServerTeam() 113{ 114 team_id id = be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE); 115 if (id < 0) { 116 ERROR("media_server: Trouble, media_addon_server is dead!\n"); 117 return -1; 118 } 119 return id; 120} 121 122 123status_t 124AppManager::SendMessage(team_id team, BMessage* message) 125{ 126 BAutolock lock(this); 127 128 AppMap::iterator found = fMap.find(team); 129 if (found == fMap.end()) 130 return B_NAME_NOT_FOUND; 131 132 return found->second.SendMessage(message); 133} 134 135 136void 137AppManager::Dump() 138{ 139 BAutolock lock(this); 140 141 printf("\n"); 142 printf("AppManager: list of applications follows:\n"); 143 144 app_info info; 145 AppMap::iterator iterator = fMap.begin(); 146 for (; iterator != fMap.end(); iterator++) { 147 app_info info; 148 be_roster->GetRunningAppInfo(iterator->first, &info); 149 printf(" team %ld \"%s\", messenger %svalid\n", iterator->first, 150 info.ref.name, iterator->second.IsValid() ? "" : "NOT "); 151 } 152 153 printf("AppManager: list end\n"); 154} 155 156 157void 158AppManager::_CleanupTeam(team_id team) 159{ 160 ASSERT(!IsLocked()); 161 162 TRACE("AppManager: cleaning up team %ld\n", team); 163 164 gNodeManager->CleanupTeam(team); 165 gBufferManager->CleanupTeam(team); 166 gNotificationManager->CleanupTeam(team); 167} 168 169 170void 171AppManager::_TeamDied(team_id team) 172{ 173 UnregisterTeam(team); 174} 175 176 177status_t 178AppManager::_BigBrotherEntry(void* self) 179{ 180 static_cast<AppManager*>(self)->_BigBrother(); 181 return 0; 182} 183 184 185/*! The BigBrother thread send ping messages to the BMediaRoster of 186 all currently running teams. If the reply times out or is wrong, 187 the team cleanup function _TeamDied() will be called. 188*/ 189void 190AppManager::_BigBrother() 191{ 192 status_t status = B_TIMED_OUT; 193 BMessage ping('PING'); 194 BMessage reply; 195 196 do { 197 if (!Lock()) 198 break; 199 200 bool startOver = false; 201 AppMap::iterator iterator = fMap.begin(); 202 for (; iterator != fMap.end(); iterator++) { 203 reply.what = 0; 204 status = iterator->second.SendMessage(&ping, &reply, 5000000, 205 2000000); 206 if (status != B_OK || reply.what != 'PONG') { 207 team_id team = iterator->first; 208 Unlock(); 209 210 _TeamDied(team); 211 startOver = true; 212 break; 213 } 214 } 215 216 if (startOver) 217 continue; 218 219 Unlock(); 220 status = acquire_sem_etc(fQuit, 1, B_RELATIVE_TIMEOUT, 2000000); 221 } while (status == B_TIMED_OUT || status == B_INTERRUPTED); 222} 223