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