1 /* 2 ** Copyright 2004-2007, Marcus Overhagen. All rights reserved. 3 ** Distributed under the terms of the OpenBeOS License. 4 */ 5 6 7 #include <Path.h> 8 #include <image.h> 9 #include <string.h> 10 11 #include "PluginManager.h" 12 #include "DataExchange.h" 13 #include "debug.h" 14 15 16 PluginManager _plugin_manager; 17 18 19 status_t 20 PluginManager::CreateReader(Reader **reader, int32 *streamCount, 21 media_file_format *mff, BDataIO *source) 22 { 23 TRACE("PluginManager::CreateReader enter\n"); 24 25 BPositionIO *seekable_source = dynamic_cast<BPositionIO *>(source); 26 if (seekable_source == 0) { 27 printf("PluginManager::CreateReader: non-seekable sources not " 28 "supported yet\n"); 29 return B_ERROR; 30 } 31 32 // get list of available readers from the server 33 server_get_readers_request request; 34 server_get_readers_reply reply; 35 status_t ret = QueryServer(SERVER_GET_READERS, &request, sizeof(request), 36 &reply, sizeof(reply)); 37 if (ret != B_OK) { 38 printf("PluginManager::CreateReader: can't get list of readers: %s\n", 39 strerror(ret)); 40 return ret; 41 } 42 43 // try each reader by calling it's Sniff function... 44 for (int32 i = 0; i < reply.count; i++) { 45 entry_ref ref = reply.ref[i]; 46 MediaPlugin *plugin = GetPlugin(ref); 47 if (!plugin) { 48 printf("PluginManager::CreateReader: GetPlugin failed\n"); 49 return B_ERROR; 50 } 51 52 ReaderPlugin *readerPlugin = dynamic_cast<ReaderPlugin*>(plugin); 53 if (!readerPlugin) { 54 printf("PluginManager::CreateReader: dynamic_cast failed\n"); 55 PutPlugin(plugin); 56 return B_ERROR; 57 } 58 59 *reader = readerPlugin->NewReader(); 60 if (*reader == NULL) { 61 printf("PluginManager::CreateReader: NewReader failed\n"); 62 PutPlugin(plugin); 63 return B_ERROR; 64 } 65 66 seekable_source->Seek(0, SEEK_SET); 67 (*reader)->Setup(seekable_source); 68 (*reader)->fMediaPlugin = plugin; 69 70 if ((*reader)->Sniff(streamCount) == B_OK) { 71 TRACE("PluginManager::CreateReader: Sniff success " 72 "(%ld stream(s))\n", *streamCount); 73 (*reader)->GetFileFormatInfo(mff); 74 return B_OK; 75 } 76 77 DestroyReader(*reader); 78 } 79 80 TRACE("PluginManager::CreateReader leave\n"); 81 return B_MEDIA_NO_HANDLER; 82 } 83 84 85 void 86 PluginManager::DestroyReader(Reader* reader) 87 { 88 if (reader != NULL) { 89 TRACE("PluginManager::DestroyReader(%p (plugin: %p))\n", reader, 90 reader->fMediaPlugin); 91 // NOTE: We have to put the plug-in after deleting the reader, 92 // since otherwise we may actually unload the code for the 93 // destructor... 94 MediaPlugin* plugin = reader->fMediaPlugin; 95 delete reader; 96 PutPlugin(plugin); 97 } 98 } 99 100 101 status_t 102 PluginManager::CreateDecoder(Decoder **_decoder, const media_format &format) 103 { 104 TRACE("PluginManager::CreateDecoder enter\n"); 105 106 // get decoder for this format from the server 107 server_get_decoder_for_format_request request; 108 server_get_decoder_for_format_reply reply; 109 request.format = format; 110 status_t ret = QueryServer(SERVER_GET_DECODER_FOR_FORMAT, &request, 111 sizeof(request), &reply, sizeof(reply)); 112 if (ret != B_OK) { 113 printf("PluginManager::CreateDecoder: can't get decoder for format: " 114 "%s\n", strerror(ret)); 115 return ret; 116 } 117 118 MediaPlugin* plugin = GetPlugin(reply.ref); 119 if (!plugin) { 120 printf("PluginManager::CreateDecoder: GetPlugin failed\n"); 121 return B_ERROR; 122 } 123 124 DecoderPlugin *decoderPlugin = dynamic_cast<DecoderPlugin *>(plugin); 125 if (!decoderPlugin) { 126 printf("PluginManager::CreateDecoder: dynamic_cast failed\n"); 127 PutPlugin(plugin); 128 return B_ERROR; 129 } 130 131 *_decoder = decoderPlugin->NewDecoder(0); 132 if (*_decoder == NULL) { 133 printf("PluginManager::CreateDecoder: NewDecoder() failed\n"); 134 PutPlugin(plugin); 135 return B_ERROR; 136 } 137 TRACE(" created decoder: %p\n", *_decoder); 138 (*_decoder)->fMediaPlugin = plugin; 139 140 TRACE("PluginManager::CreateDecoder leave\n"); 141 142 return B_OK; 143 } 144 145 146 status_t 147 PluginManager::CreateDecoder(Decoder **decoder, const media_codec_info &mci) 148 { 149 // TODO 150 debugger("not implemented"); 151 return B_ERROR; 152 } 153 154 155 status_t 156 PluginManager::GetDecoderInfo(Decoder *decoder, 157 media_codec_info *out_info) const 158 { 159 if (!decoder) 160 return B_BAD_VALUE; 161 162 decoder->GetCodecInfo(out_info); 163 // TODO: 164 // out_info->id = 165 // out_info->sub_id = 166 return B_OK; 167 } 168 169 170 void 171 PluginManager::DestroyDecoder(Decoder *decoder) 172 { 173 if (decoder != NULL) { 174 TRACE("PluginManager::DestroyDecoder(%p, plugin: %p)\n", decoder, 175 decoder->fMediaPlugin); 176 // NOTE: We have to put the plug-in after deleting the decoder, 177 // since otherwise we may actually unload the code for the 178 // destructor... 179 MediaPlugin* plugin = decoder->fMediaPlugin; 180 delete decoder; 181 PutPlugin(plugin); 182 } 183 } 184 185 186 // #pragma mark - 187 188 189 PluginManager::PluginManager() 190 { 191 CALLED(); 192 fLocker = new BLocker; 193 fPluginList = new List<plugin_info>; 194 } 195 196 197 PluginManager::~PluginManager() 198 { 199 CALLED(); 200 for (int i = fPluginList->CountItems() - 1; i >= 0; i--) { 201 plugin_info *info = NULL; 202 fPluginList->Get(i, &info); 203 printf("PluginManager: Error, unloading PlugIn %s with usecount " 204 "%d\n", info->name, info->usecount); 205 delete info->plugin; 206 unload_add_on(info->image); 207 } 208 delete fLocker; 209 } 210 211 212 MediaPlugin * 213 PluginManager::GetPlugin(const entry_ref &ref) 214 { 215 TRACE("PluginManager::GetPlugin(%s)\n", ref.name); 216 fLocker->Lock(); 217 218 MediaPlugin *plugin; 219 plugin_info *pinfo; 220 plugin_info info; 221 222 for (fPluginList->Rewind(); fPluginList->GetNext(&pinfo); ) { 223 if (0 == strcmp(ref.name, pinfo->name)) { 224 plugin = pinfo->plugin; 225 pinfo->usecount++; 226 TRACE(" found existing plugin: %p\n", pinfo->plugin); 227 fLocker->Unlock(); 228 return plugin; 229 } 230 } 231 232 if (LoadPlugin(ref, &info.plugin, &info.image) < B_OK) { 233 printf("PluginManager: Error, loading PlugIn %s failed\n", ref.name); 234 fLocker->Unlock(); 235 return NULL; 236 } 237 238 strcpy(info.name, ref.name); 239 info.usecount = 1; 240 fPluginList->Insert(info); 241 242 TRACE("PluginManager: PlugIn %s loaded\n", ref.name); 243 244 plugin = info.plugin; 245 TRACE(" loaded plugin: %p\n", plugin); 246 247 fLocker->Unlock(); 248 return plugin; 249 } 250 251 252 void 253 PluginManager::PutPlugin(MediaPlugin* plugin) 254 { 255 TRACE("PluginManager::PutPlugin()\n"); 256 fLocker->Lock(); 257 258 plugin_info *pinfo; 259 260 for (fPluginList->Rewind(); fPluginList->GetNext(&pinfo); ) { 261 if (plugin == pinfo->plugin) { 262 pinfo->usecount--; 263 if (pinfo->usecount == 0) { 264 TRACE(" deleting %p\n", pinfo->plugin); 265 delete pinfo->plugin; 266 TRACE(" unloading add-on: %ld\n\n", pinfo->image); 267 unload_add_on(pinfo->image); 268 fPluginList->RemoveCurrent(); 269 } 270 fLocker->Unlock(); 271 return; 272 } 273 } 274 275 printf("PluginManager: Error, can't put PlugIn %p\n", plugin); 276 277 fLocker->Unlock(); 278 } 279 280 281 status_t 282 PluginManager::LoadPlugin(const entry_ref &ref, MediaPlugin **plugin, 283 image_id *image) 284 { 285 BPath p(&ref); 286 287 TRACE("PluginManager: LoadPlugin trying to load %s\n", p.Path()); 288 289 image_id id; 290 id = load_add_on(p.Path()); 291 TRACE(" loaded add-on: %ld\n", id); 292 if (id < 0) 293 return B_ERROR; 294 295 MediaPlugin *(*instantiate_plugin_func)(); 296 297 if (get_image_symbol(id, "instantiate_plugin", B_SYMBOL_TYPE_TEXT, 298 (void**)&instantiate_plugin_func) < B_OK) { 299 printf("PluginManager: Error, LoadPlugin can't find " 300 "instantiate_plugin in %s\n", p.Path()); 301 unload_add_on(id); 302 return B_ERROR; 303 } 304 305 MediaPlugin *pl; 306 307 pl = (*instantiate_plugin_func)(); 308 if (pl == NULL) { 309 printf("PluginManager: Error, LoadPlugin instantiate_plugin in %s " 310 "returned NULL\n", p.Path()); 311 unload_add_on(id); 312 return B_ERROR; 313 } 314 315 *plugin = pl; 316 *image = id; 317 return B_OK; 318 } 319