xref: /haiku/src/kits/media/PluginManager.cpp (revision b9a5b9a6ee494261f2882bfc0ee9fde92282bef6)
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