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