xref: /haiku/src/kits/media/MediaAddOn.cpp (revision a381c8a06378de22ff08adf4282b4e3f7e50d250)
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 #include <MediaAddOn.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include "debug.h"
34 #include "DataExchange.h"
35 
36 /*
37  * some little helper function
38  */
39 
40 static inline char *newstrdup(const char *str);
41 char *newstrdup(const char *str)
42 {
43 	if (str == NULL)
44 		return NULL;
45 	int len = strlen(str) + 1;
46 	char *p = new char[len];
47 	memcpy(p, str, len);
48 	return p;
49 }
50 
51 #define FLATTEN_MAGIC 		'CODE'
52 #define FLATTEN_TYPECODE	'DFIT'
53 
54 /*************************************************************
55  * public dormant_node_info
56  *************************************************************/
57 
58 // final & verified
59 dormant_node_info::dormant_node_info()
60 	: addon(-1),
61 	flavor_id(-1)
62 {
63 	name[0] = '\0';
64 }
65 
66 // final
67 dormant_node_info::~dormant_node_info()
68 {
69 }
70 
71 /*************************************************************
72  * private flavor_info
73  *************************************************************/
74 
75 /* DO NOT IMPLEMENT */
76 /*
77 flavor_info &flavor_info::operator=(const flavor_info &other)
78 */
79 
80 /*************************************************************
81  * public dormant_flavor_info
82  *************************************************************/
83 
84 // final & verified
85 dormant_flavor_info::dormant_flavor_info()
86 {
87 	name = 0;
88 	info = 0;
89 	kinds = 0;
90 	flavor_flags = 0;
91 	internal_id = 0;
92 	possible_count = 0;
93 	in_format_count = 0;
94 	in_format_flags = 0;
95 	in_formats = 0;
96 	out_format_count = 0;
97 	out_format_flags = 0;
98 	out_formats = 0;
99 }
100 
101 
102 /* virtual */
103 dormant_flavor_info::~dormant_flavor_info()
104 {
105 	delete [] name;
106 	delete [] info;
107 	delete [] in_formats;
108 	delete [] out_formats;
109 }
110 
111 
112 dormant_flavor_info::dormant_flavor_info(const dormant_flavor_info &clone)
113 {
114 	*this = clone;
115 }
116 
117 
118 dormant_flavor_info &
119 dormant_flavor_info::operator=(const dormant_flavor_info &clone)
120 {
121 	// call operator=(const flavor_info &clone) to copy the flavor_info base class
122 	*this = static_cast<const flavor_info>(clone);
123 	// copy the dormant_node_info member variable
124 	node_info = clone.node_info;
125 	return *this;
126 }
127 
128 
129 dormant_flavor_info &
130 dormant_flavor_info::operator=(const flavor_info &clone)
131 {
132 	delete [] name;
133 	delete [] info;
134 	delete [] in_formats;
135 	delete [] out_formats;
136 
137 	name = newstrdup(clone.name);
138 	info = newstrdup(clone.info);
139 
140 	kinds = clone.kinds;
141 	flavor_flags = clone.flavor_flags;
142 	internal_id = clone.internal_id;
143 	possible_count = clone.possible_count;
144 
145 	in_format_count = clone.in_format_count;
146 	in_format_flags = clone.in_format_flags;
147 	out_format_count = clone.out_format_count;
148 	out_format_flags = clone.out_format_flags;
149 
150 	if (in_format_count > 0) {
151 		media_format *temp;
152 		temp = new media_format[in_format_count];
153 		for (int i = 0; i < in_format_count; i++)
154 			temp[i] = clone.in_formats[i];
155 		in_formats = temp;
156 	} else {
157 		in_formats = 0;
158 	}
159 
160 	if (out_format_count > 0) {
161 		media_format *temp;
162 		temp = new media_format[out_format_count];
163 		for (int i = 0; i < out_format_count; i++)
164 			temp[i] = clone.out_formats[i];
165 		out_formats = temp;
166 	} else {
167 		out_formats = 0;
168 	}
169 
170 	// initialize node_info with default values from dormant_node_info constructor
171 	dormant_node_info temp;
172 	node_info = temp;
173 
174 	return *this;
175 }
176 
177 
178 void
179 dormant_flavor_info::set_name(const char *in_name)
180 {
181 	delete [] name;
182 	name = newstrdup(in_name);
183 }
184 
185 
186 void
187 dormant_flavor_info::set_info(const char *in_info)
188 {
189 	delete [] info;
190 	info = newstrdup(in_info);
191 }
192 
193 
194 void
195 dormant_flavor_info::add_in_format(const media_format &in_format)
196 {
197 	media_format *temp;
198 	temp = new media_format[in_format_count + 1];
199 	for (int i = 0; i < in_format_count; i++)
200 		temp[i] = in_formats[i];
201 	temp[in_format_count] = in_format;
202 	delete [] in_formats;
203 	in_format_count += 1;
204 	in_formats = temp;
205 }
206 
207 
208 void
209 dormant_flavor_info::add_out_format(const media_format &out_format)
210 {
211 	media_format *temp;
212 	temp = new media_format[out_format_count + 1];
213 	for (int i = 0; i < out_format_count; i++)
214 		temp[i] = out_formats[i];
215 	temp[out_format_count] = out_format;
216 	delete [] out_formats;
217 	out_format_count += 1;
218 	out_formats = temp;
219 }
220 
221 
222 /* virtual */ bool
223 dormant_flavor_info::IsFixedSize() const
224 {
225 	return false;
226 }
227 
228 
229 /* virtual */ type_code
230 dormant_flavor_info::TypeCode() const
231 {
232 	return FLATTEN_TYPECODE;
233 }
234 
235 
236 /* virtual */ ssize_t
237 dormant_flavor_info::FlattenedSize() const
238 {
239 	ssize_t size = 0;
240 	// magic
241 	size += sizeof(int32);
242 	// size
243 	size += sizeof(int32);
244 	// struct flavor_info
245 	size += sizeof(int32) + strlen(name);
246 	size += sizeof(int32) + strlen(info);
247 	size += sizeof(kinds);
248 	size += sizeof(flavor_flags);
249 	size += sizeof(internal_id);
250 	size += sizeof(possible_count);
251 	size += sizeof(in_format_count);
252 	size += sizeof(in_format_flags);
253 	size += in_format_count * sizeof(media_format);
254 	size += sizeof(out_format_count);
255 	size += sizeof(out_format_flags);
256 	size += out_format_count * sizeof(media_format);
257 	// struct dormant_node_info	node_info
258 	size += sizeof(node_info);
259 
260 	return size;
261 }
262 
263 
264 /* virtual */ status_t
265 dormant_flavor_info::Flatten(void *buffer,
266 							 ssize_t size) const
267 {
268 	if (size < FlattenedSize())
269 		return B_ERROR;
270 
271 	char *buf = (char *)buffer;
272 	int32 namelen = name ? (int32)strlen(name) : -1;
273 	int32 infolen = info ? (int32)strlen(info) : -1;
274 
275 	// magic
276 	*(int32*)buf = FLATTEN_MAGIC; buf += sizeof(int32);
277 
278 	// size
279 	*(int32*)buf = FlattenedSize(); buf += sizeof(int32);
280 
281 	// struct flavor_info
282 	*(int32*)buf = namelen; buf += sizeof(int32);
283 	if (namelen > 0) {
284 		memcpy(buf,name,namelen);
285 		buf += namelen;
286 	}
287 	*(int32*)buf = infolen; buf += sizeof(int32);
288 	if (infolen > 0) {
289 		memcpy(buf,info,infolen);
290 		buf += infolen;
291 	}
292 
293 	*(uint64*)buf = kinds; buf += sizeof(uint64);
294 	*(uint32*)buf = flavor_flags; buf += sizeof(uint32);
295 	*(int32*)buf = internal_id; buf += sizeof(int32);
296 	*(int32*)buf = possible_count; buf += sizeof(int32);
297 	*(int32*)buf = in_format_count; buf += sizeof(int32);
298 	*(uint32*)buf = in_format_flags; buf += sizeof(uint32);
299 
300 	// XXX FIXME! we should not!!! make flat copies	of media_format
301 	memcpy(buf,in_formats,in_format_count * sizeof(media_format)); buf += in_format_count * sizeof(media_format);
302 
303 	*(int32*)buf = out_format_count; buf += sizeof(int32);
304 	*(uint32*)buf = out_format_flags; buf += sizeof(uint32);
305 
306 	// XXX FIXME! we should not!!! make flat copies	of media_format
307 	memcpy(buf,out_formats,out_format_count * sizeof(media_format)); buf += out_format_count * sizeof(media_format);
308 
309 	*(dormant_node_info*)buf = node_info; buf += sizeof(dormant_node_info);
310 
311 	return B_OK;
312 }
313 
314 
315 /* virtual */ status_t
316 dormant_flavor_info::Unflatten(type_code c,
317 							   const void *buffer,
318 							   ssize_t size)
319 {
320 	if (c != FLATTEN_TYPECODE)
321 		return B_ERROR;
322 	if (size < 8)
323 		return B_ERROR;
324 
325 	const char *buf = (const char *)buffer;
326 	int32 namelen;
327 	int32 infolen;
328 
329 	// magic
330 	if (*(int32*)buf != FLATTEN_MAGIC)
331 		return B_ERROR;
332 	buf += sizeof(int32);
333 
334 	// size
335 	if (*(int32*)buf > size)
336 		return B_ERROR;
337 	buf += sizeof(int32);
338 
339 
340 	delete [] name;
341 	delete [] info;
342 	delete [] in_formats;
343 	delete [] out_formats;
344 	name = 0;
345 	info = 0;
346 	in_formats = 0;
347 	out_formats = 0;
348 
349 
350 	// struct flavor_info
351 	namelen = *(int32*)buf; buf += sizeof(int32);
352 	if (namelen >= 0) { // if namelen is -1, we leave name = 0
353 		name = new char [namelen + 1];
354 		memcpy(name,buf,namelen);
355 		name[namelen] = 0;
356 		buf += namelen;
357 	}
358 
359 	infolen = *(int32*)buf; buf += sizeof(int32);
360 	if (infolen >= 0) { // if infolen is -1, we leave info = 0
361 		info = new char [infolen + 1];
362 		memcpy(info,buf,infolen);
363 		info[infolen] = 0;
364 		buf += infolen;
365 	}
366 
367 	kinds = *(uint64*)buf; buf += sizeof(uint64);
368 	flavor_flags = *(uint32*)buf; buf += sizeof(uint32);
369 	internal_id = *(int32*)buf; buf += sizeof(int32);
370 	possible_count = *(int32*)buf; buf += sizeof(int32);
371 	in_format_count = *(int32*)buf; buf += sizeof(int32);
372 	in_format_flags = *(uint32*)buf; buf += sizeof(uint32);
373 
374 	// XXX FIXME! we should not!!! make flat copies	of media_format
375 	if (in_format_count > 0) {
376 		in_formats = new media_format[in_format_count];
377 		memcpy((media_format *)in_formats,buf,in_format_count * sizeof(media_format));
378 		buf += in_format_count * sizeof(media_format);
379 	}
380 
381 	out_format_count = *(int32*)buf; buf += sizeof(int32);
382 	out_format_flags = *(uint32*)buf; buf += sizeof(uint32);
383 
384 	// XXX FIXME! we should not!!! make flat copies	of media_format
385 	if (out_format_count > 0) {
386 		out_formats = new media_format[out_format_count];
387 		memcpy((media_format *)out_formats,buf,out_format_count * sizeof(media_format));
388 		buf += out_format_count * sizeof(media_format);
389 	}
390 
391 	node_info = *(dormant_node_info*)buf; buf += sizeof(dormant_node_info);
392 
393 	return B_OK;
394 }
395 
396 /*************************************************************
397  * public BMediaAddOn
398  *************************************************************/
399 
400 /* explicit */
401 BMediaAddOn::BMediaAddOn(image_id image) :
402 	fImage(image),
403 	fAddon(0)
404 {
405 	CALLED();
406 }
407 
408 
409 /* virtual */
410 BMediaAddOn::~BMediaAddOn()
411 {
412 	CALLED();
413 }
414 
415 
416 /* virtual */ status_t
417 BMediaAddOn::InitCheck(const char **out_failure_text)
418 {
419 	CALLED();
420 	// only to be implemented by derived classes
421 	*out_failure_text = "no error";
422 	return B_OK;
423 }
424 
425 
426 /* virtual */ int32
427 BMediaAddOn::CountFlavors()
428 {
429 	CALLED();
430 	// only to be implemented by derived classes
431 	return 0;
432 }
433 
434 
435 /* virtual */ status_t
436 BMediaAddOn::GetFlavorAt(int32 n,
437 						 const flavor_info **out_info)
438 {
439 	CALLED();
440 	// only to be implemented by derived classes
441 	return B_ERROR;
442 }
443 
444 
445 /* virtual */ BMediaNode *
446 BMediaAddOn::InstantiateNodeFor(const flavor_info *info,
447 								BMessage *config,
448 								status_t *out_error)
449 {
450 	CALLED();
451 	// only to be implemented by derived classes
452 	return NULL;
453 }
454 
455 
456 /* virtual */ status_t
457 BMediaAddOn::GetConfigurationFor(BMediaNode *your_node,
458 								 BMessage *into_message)
459 {
460 	CALLED();
461 	// only to be implemented by derived classes
462 	return B_ERROR;
463 }
464 
465 
466 /* virtual */ bool
467 BMediaAddOn::WantsAutoStart()
468 {
469 	CALLED();
470 	// only to be implemented by derived classes
471 	return false;
472 }
473 
474 
475 /* virtual */ status_t
476 BMediaAddOn::AutoStart(int in_count,
477 					   BMediaNode **out_node,
478 					   int32 *out_internal_id,
479 					   bool *out_has_more)
480 {
481 	CALLED();
482 	// only to be implemented by derived classes
483 	return B_ERROR;
484 }
485 
486 
487 /* virtual */ status_t
488 BMediaAddOn::SniffRef(const entry_ref &file,
489 					  BMimeType *io_mime_type,
490 					  float *out_quality,
491 					  int32 *out_internal_id)
492 {
493 	CALLED();
494 	// only to be implemented by BFileInterface derived classes
495 	return B_ERROR;
496 }
497 
498 
499 /* virtual */ status_t
500 BMediaAddOn::SniffType(const BMimeType &type,
501 					   float *out_quality,
502 					   int32 *out_internal_id)
503 {
504 	CALLED();
505 	// only to be implemented by BFileInterface derived classes
506 	return B_ERROR;
507 }
508 
509 
510 /* virtual */ status_t
511 BMediaAddOn::GetFileFormatList(int32 flavor_id,
512 							   media_file_format *out_writable_formats,
513 							   int32 in_write_items,
514 							   int32 *out_write_items,
515 							   media_file_format *out_readable_formats,
516 							   int32 in_read_items,
517 							   int32 *out_read_items,
518 							   void *_reserved)
519 {
520 	CALLED();
521 	// only to be implemented by BFileInterface derived classes
522 	return B_ERROR;
523 }
524 
525 
526 /* virtual */ status_t
527 BMediaAddOn::SniffTypeKind(const BMimeType &type,
528 						   uint64 in_kinds,
529 						   float *out_quality,
530 						   int32 *out_internal_id,
531 						   void *_reserved)
532 {
533 	CALLED();
534 	// only to be implemented by BFileInterface derived classes
535 	return B_ERROR;
536 }
537 
538 
539 image_id
540 BMediaAddOn::ImageID()
541 {
542 	return fImage;
543 }
544 
545 
546 media_addon_id
547 BMediaAddOn::AddonID()
548 {
549 	return fAddon;
550 }
551 
552 /*************************************************************
553  * protected BMediaAddOn
554  *************************************************************/
555 
556 status_t
557 BMediaAddOn::NotifyFlavorChange()
558 {
559 	CALLED();
560 	if (fAddon == 0)
561 		return B_ERROR;
562 
563 	addonserver_rescan_mediaaddon_flavors_command command;
564 	command.addonid = fAddon;
565 	return SendToAddonServer(ADDONSERVER_RESCAN_MEDIAADDON_FLAVORS, &command, sizeof(command));
566 }
567 
568 /*************************************************************
569  * private BMediaAddOn
570  *************************************************************/
571 
572 /*
573 unimplemented:
574 BMediaAddOn::BMediaAddOn()
575 BMediaAddOn::BMediaAddOn(const BMediaAddOn &clone)
576 BMediaAddOn & BMediaAddOn::operator=(const BMediaAddOn &clone)
577 */
578 
579 
580 /*************************************************************
581  * private BMediaAddOn
582  *************************************************************/
583 
584 extern "C" {
585 	// declared here to remove them from the class header file
586 	status_t _Reserved_MediaAddOn_0__11BMediaAddOnPv(void *, void *); /* now used for BMediaAddOn::GetFileFormatList */
587 	status_t _Reserved_MediaAddOn_1__11BMediaAddOnPv(void *, void *); /* now used for BMediaAddOn::SniffTypeKind */
588 	status_t _Reserved_MediaAddOn_0__11BMediaAddOnPv(void *, void *) { return B_ERROR; }
589 	status_t _Reserved_MediaAddOn_1__11BMediaAddOnPv(void *, void *) { return B_ERROR; }
590 };
591 
592 status_t BMediaAddOn::_Reserved_MediaAddOn_2(void *) { return B_ERROR; }
593 status_t BMediaAddOn::_Reserved_MediaAddOn_3(void *) { return B_ERROR; }
594 status_t BMediaAddOn::_Reserved_MediaAddOn_4(void *) { return B_ERROR; }
595 status_t BMediaAddOn::_Reserved_MediaAddOn_5(void *) { return B_ERROR; }
596 status_t BMediaAddOn::_Reserved_MediaAddOn_6(void *) { return B_ERROR; }
597 status_t BMediaAddOn::_Reserved_MediaAddOn_7(void *) { return B_ERROR; }
598 
599