xref: /haiku/src/kits/media/MediaDefs.cpp (revision d0ac609964842f8cdb6d54b3c539c6c15293e172)
1 /*
2  * Copyright 2015, Dario Casalinuovo
3  * Copyright 2004, 2006, Jérôme Duval.
4  * Copyright 2003-2004, Andrew Bachmann.
5  * Copyright 2002-2004, 2006 Marcus Overhagen.
6  * Copyright 2002, Eric Jaessler.
7  * All rights reserved. Distributed under the terms of the MIT license.
8  */
9 
10 
11 #include <MediaDefs.h>
12 
13 #include <Application.h>
14 #include <Bitmap.h>
15 #include <Catalog.h>
16 #include <IconUtils.h>
17 #include <Locale.h>
18 #include <MediaNode.h>
19 #include <MediaRoster.h>
20 #include <Node.h>
21 #include <Notification.h>
22 #include <Roster.h>
23 
24 #include <inttypes.h>
25 #include <stdio.h>
26 #include <string.h>
27 
28 #include "AddOnManager.h"
29 #include "DataExchange.h"
30 #include "debug.h"
31 #include "MediaMisc.h"
32 
33 
34 #define META_DATA_MAX_SIZE			(16 << 20)
35 #define META_DATA_AREA_MIN_SIZE		32000
36 
37 #undef B_TRANSLATION_CONTEXT
38 #define B_TRANSLATION_CONTEXT "MediaDefs"
39 
40 
41 // #pragma mark - media_destination
42 
43 
44 media_destination::media_destination(port_id port, int32 id)
45 	:
46 	port(port),
47 	id(id)
48 {
49 }
50 
51 
52 media_destination::media_destination(const media_destination& clone)
53 	:
54 	port(clone.port),
55 	id(clone.id)
56 {
57 }
58 
59 
60 media_destination&
61 media_destination::operator=(const media_destination& clone)
62 {
63 	port = clone.port;
64 	id = clone.id;
65 	return *this;
66 }
67 
68 
69 media_destination::media_destination()
70 	:
71 	port(-1),
72 	id(-1)
73 {
74 }
75 
76 
77 media_destination::~media_destination()
78 {
79 }
80 
81 
82 media_destination media_destination::null(-1, -1);
83 
84 
85 // #pragma mark - media_source
86 
87 
88 media_source::media_source(port_id port,
89 						   int32 id)
90 	:
91 	port(port),
92 	id(id)
93 {
94 }
95 
96 
97 media_source::media_source(const media_source& clone)
98 	:
99 	port(clone.port),
100 	id(clone.id)
101 {
102 }
103 
104 
105 media_source&
106 media_source::operator=(const media_source& clone)
107 {
108 	port = clone.port;
109 	id = clone.id;
110 	return *this;
111 }
112 
113 
114 media_source::media_source()
115 	:
116 	port(-1),
117 	id(-1)
118 {
119 }
120 
121 
122 media_source::~media_source()
123 {
124 }
125 
126 
127 media_source media_source::null(-1, -1);
128 
129 
130 // #pragma mark -
131 
132 
133 bool
134 operator==(const media_destination& a, const media_destination& b)
135 {
136 	return a.port == b.port && a.id == b.id;
137 }
138 
139 
140 bool
141 operator!=(const media_destination& a, const media_destination& b)
142 {
143 	return a.port != b.port || a.id != b.id;
144 }
145 
146 
147 bool
148 operator<(const media_destination& a, const media_destination& b)
149 {
150 	UNIMPLEMENTED();
151 	return false;
152 }
153 
154 
155 bool
156 operator==(const media_source& a, const media_source& b)
157 {
158 	return a.port == b.port && a.id == b.id;
159 }
160 
161 
162 bool
163 operator!=(const media_source& a, const media_source& b)
164 {
165 	return a.port != b.port || a.id != b.id;
166 }
167 
168 
169 bool
170 operator<(const media_source& a, const media_source& b)
171 {
172 	UNIMPLEMENTED();
173 	return false;
174 }
175 
176 
177 bool
178 operator==(const media_node& a, const media_node& b)
179 {
180 	return a.node == b.node && a.port == b.port && a.kind == b.kind;
181 }
182 
183 
184 bool
185 operator!=(const media_node& a, const media_node& b)
186 {
187 	return a.node != b.node || a.port != b.port || a.kind != b.kind;
188 }
189 
190 
191 bool
192 operator<(const media_node& a, const media_node& b)
193 {
194 	UNIMPLEMENTED();
195 	return false;
196 }
197 
198 
199 // #pragma mark -
200 
201 
202 media_multi_audio_format media_raw_audio_format::wildcard;
203 
204 media_multi_audio_format media_multi_audio_format::wildcard;
205 
206 media_encoded_audio_format media_encoded_audio_format::wildcard = {{0}};
207 
208 media_video_display_info media_video_display_info::wildcard = {(color_space)0};
209 
210 media_raw_video_format media_raw_video_format::wildcard = {0};
211 
212 media_encoded_video_format media_encoded_video_format::wildcard = {{0}};
213 
214 media_multistream_format media_multistream_format::wildcard = {0};
215 
216 
217 // #pragma mark - media_format::Matches() support
218 
219 
220 static bool
221 raw_audio_format_matches(const media_raw_audio_format& a,
222 	const media_raw_audio_format& b)
223 {
224 	if (a.frame_rate != 0 && b.frame_rate != 0 && a.frame_rate != b.frame_rate)
225 		return false;
226 	if (a.channel_count != 0 && b.channel_count != 0
227 		&& a.channel_count != b.channel_count) {
228 		return false;
229 	}
230 	if (a.format != 0 && b.format != 0 && a.format != b.format)
231 		return false;
232 	if (a.byte_order != 0 && b.byte_order != 0 && a.byte_order != b.byte_order)
233 		return false;
234 	if (a.buffer_size != 0 && b.buffer_size != 0
235 		&& a.buffer_size != b.buffer_size) {
236 		return false;
237 	}
238 	if (a.frame_rate != 0 && b.frame_rate != 0 && a.frame_rate != b.frame_rate)
239 		return false;
240 	return true;
241 }
242 
243 
244 static bool
245 multi_audio_info_matches(const media_multi_audio_info& a,
246 	const media_multi_audio_info& b)
247 {
248 	if (a.channel_mask != 0 && b.channel_mask != 0
249 		&& a.channel_mask != b.channel_mask) {
250 		return false;
251 	}
252 	if (a.valid_bits != 0 && b.valid_bits != 0 && a.valid_bits != b.valid_bits)
253 		return false;
254 	if (a.matrix_mask != 0 && b.matrix_mask != 0
255 		&& a.matrix_mask != b.matrix_mask) {
256 		return false;
257 	}
258 	return true;
259 }
260 
261 
262 static bool
263 multi_audio_format_matches(const media_multi_audio_format& a,
264 	const media_multi_audio_format& b)
265 {
266 	return raw_audio_format_matches(a, b) && multi_audio_info_matches(a, b);
267 }
268 
269 
270 static bool
271 raw_video_format_matches(const media_raw_video_format& a,
272 	const media_raw_video_format& b)
273 {
274 	if (a.field_rate != 0 && b.field_rate != 0
275 		&& a.field_rate != b.field_rate) {
276 		return false;
277 	}
278 	if (a.interlace != 0 && b.interlace != 0
279 		&& a.interlace != b.interlace) {
280 		return false;
281 	}
282 	if (a.first_active != 0 && b.first_active != 0
283 		&& a.first_active != b.first_active) {
284 		return false;
285 	}
286 	if (a.last_active != 0 && b.last_active != 0
287 		&& a.last_active != b.last_active) {
288 		return false;
289 	}
290 	if (a.orientation != 0 && b.orientation != 0
291 		&& a.orientation != b.orientation) {
292 		return false;
293 	}
294 	if (a.pixel_width_aspect != 0 && b.pixel_width_aspect != 0
295 		&& a.pixel_width_aspect != b.pixel_width_aspect) {
296 		return false;
297 	}
298 	if (a.pixel_height_aspect != 0 && b.pixel_height_aspect != 0
299 		&& a.pixel_height_aspect != b.pixel_height_aspect) {
300 		return false;
301 	}
302 	if (a.display.format != 0 && b.display.format != 0
303 		&& a.display.format != b.display.format) {
304 		return false;
305 	}
306 	if (a.display.line_width != 0 && b.display.line_width != 0
307 		&& a.display.line_width != b.display.line_width) {
308 		return false;
309 	}
310 	if (a.display.line_count != 0 && b.display.line_count != 0
311 		&& a.display.line_count != b.display.line_count) {
312 		return false;
313 	}
314 	if (a.display.bytes_per_row != 0 && b.display.bytes_per_row != 0
315 		&& a.display.bytes_per_row != b.display.bytes_per_row) {
316 		return false;
317 	}
318 	if (a.display.pixel_offset != 0 && b.display.pixel_offset != 0
319 		&& a.display.pixel_offset != b.display.pixel_offset) {
320 		return false;
321 	}
322 	if (a.display.line_offset != 0 && b.display.line_offset != 0
323 		&& a.display.line_offset != b.display.line_offset) {
324 		return false;
325 	}
326 	if (a.display.flags != 0 && b.display.flags != 0
327 		&& a.display.flags != b.display.flags) {
328 		return false;
329 	}
330 
331 	return true;
332 }
333 
334 
335 static bool
336 multistream_format_matches(const media_multistream_format& a,
337 	const media_multistream_format& b)
338 {
339 	if (a.avg_bit_rate != 0 && b.avg_bit_rate != 0
340 		&& a.avg_bit_rate != b.avg_bit_rate) {
341 		return false;
342 	}
343 	if (a.max_bit_rate != 0 && b.max_bit_rate != 0
344 		&& a.max_bit_rate != b.max_bit_rate) {
345 		return false;
346 	}
347 	if (a.avg_chunk_size != 0 && b.avg_chunk_size != 0
348 		&& a.avg_chunk_size != b.avg_chunk_size) {
349 		return false;
350 	}
351 	if (a.max_chunk_size != 0 && b.max_chunk_size != 0
352 		&& a.max_chunk_size != b.max_chunk_size) {
353 		return false;
354 	}
355 	if (a.flags != 0 && b.flags != 0 && a.flags != b.flags)
356 		return false;
357 	if (a.format != 0 && b.format != 0 && a.format != b.format)
358 		return false;
359 
360 	if (a.format == 0 && b.format == 0) {
361 		// TODO: How do we compare two formats with no type?
362 		return true;
363 	}
364 
365 	switch ((a.format != 0) ? a.format : b.format) {
366 		default:
367 			return true; // TODO: really?
368 
369 		case media_multistream_format::B_VID:
370 			if (a.u.vid.frame_rate != 0 && b.u.vid.frame_rate != 0
371 				&& a.u.vid.frame_rate != b.u.vid.frame_rate) {
372 				return false;
373 			}
374 			if (a.u.vid.width != 0 && b.u.vid.width != 0
375 				&& a.u.vid.width != b.u.vid.width) {
376 				return false;
377 			}
378 			if (a.u.vid.height != 0 && b.u.vid.height != 0
379 				&& a.u.vid.height != b.u.vid.height) {
380 				return false;
381 			}
382 			if (a.u.vid.space != 0 && b.u.vid.space != 0
383 				&& a.u.vid.space != b.u.vid.space) {
384 				return false;
385 			}
386 			if (a.u.vid.sampling_rate != 0 && b.u.vid.sampling_rate != 0
387 				&& a.u.vid.sampling_rate != b.u.vid.sampling_rate) {
388 				return false;
389 			}
390 			if (a.u.vid.sample_format != 0 && b.u.vid.sample_format != 0
391 				&& a.u.vid.sample_format != b.u.vid.sample_format) {
392 				return false;
393 			}
394 			if (a.u.vid.byte_order != 0 && b.u.vid.byte_order != 0
395 				&& a.u.vid.byte_order != b.u.vid.byte_order) {
396 				return false;
397 			}
398 			if (a.u.vid.channel_count != 0 && b.u.vid.channel_count != 0
399 				&& a.u.vid.channel_count != b.u.vid.channel_count) {
400 				return false;
401 			}
402 			return true;
403 
404 		case media_multistream_format::B_AVI:
405 			if (a.u.avi.us_per_frame != 0 && b.u.avi.us_per_frame != 0
406 				&& a.u.avi.us_per_frame != b.u.avi.us_per_frame) {
407 				return false;
408 			}
409 			if (a.u.avi.width != 0 && b.u.avi.width != 0
410 				&& a.u.avi.width != b.u.avi.width) {
411 				return false;
412 			}
413 			if (a.u.avi.height != 0 && b.u.avi.height != 0
414 				&& a.u.avi.height != b.u.avi.height) {
415 				return false;
416 			}
417 			if (a.u.avi.type_count != 0 && b.u.avi.type_count != 0
418 				&& a.u.avi.type_count != b.u.avi.type_count) {
419 				return false;
420 			}
421 			if (a.u.avi.types[0] != 0 && b.u.avi.types[0] != 0
422 				&& a.u.avi.types[0] != b.u.avi.types[0]) {
423 				return false;
424 			}
425 			if (a.u.avi.types[1] != 0 && b.u.avi.types[1] != 0
426 				&& a.u.avi.types[1] != b.u.avi.types[1]) {
427 				return false;
428 			}
429 			if (a.u.avi.types[2] != 0 && b.u.avi.types[2] != 0
430 				&& a.u.avi.types[2] != b.u.avi.types[2]) {
431 				return false;
432 			}
433 			if (a.u.avi.types[3] != 0 && b.u.avi.types[3] != 0
434 				&& a.u.avi.types[3] != b.u.avi.types[3]) {
435 				return false;
436 			}
437 			if (a.u.avi.types[4] != 0 && b.u.avi.types[4] != 0
438 				&& a.u.avi.types[4] != b.u.avi.types[4]) {
439 				return false;
440 			}
441 			return true;
442 	}
443 }
444 
445 
446 static bool
447 encoded_audio_format_matches(const media_encoded_audio_format& a,
448 	const media_encoded_audio_format& b)
449 {
450 	if (!raw_audio_format_matches(a.output, b.output))
451 		return false;
452 	if (a.encoding != 0 && b.encoding != 0 && a.encoding != b.encoding)
453 		return false;
454 	if (a.bit_rate != 0 && b.bit_rate != 0 && a.bit_rate != b.bit_rate)
455 		return false;
456 	if (a.frame_size != 0 && b.frame_size != 0 && a.frame_size != b.frame_size)
457 		return false;
458 	if (!multi_audio_info_matches(a.multi_info, b.multi_info))
459 		return false;
460 
461 	if (a.encoding == 0 && b.encoding == 0)
462 		return true; // can't compare
463 
464 	switch((a.encoding != 0) ? a.encoding : b.encoding) {
465 		case media_encoded_audio_format::B_ANY:
466 		default:
467 			return true;
468 	}
469 }
470 
471 
472 static bool
473 encoded_video_format_matches(const media_encoded_video_format& a,
474 	const media_encoded_video_format& b)
475 {
476 	if (!raw_video_format_matches(a.output, b.output))
477 		return false;
478 	if (a.encoding != 0 && b.encoding != 0 && a.encoding != b.encoding)
479 		return false;
480 
481 	if (a.avg_bit_rate != 0 && b.avg_bit_rate != 0
482 		&& a.avg_bit_rate != b.avg_bit_rate) {
483 		return false;
484 	}
485 	if (a.max_bit_rate != 0 && b.max_bit_rate != 0
486 		&& a.max_bit_rate != b.max_bit_rate) {
487 		return false;
488 	}
489 	if (a.frame_size != 0 && b.frame_size != 0
490 		&& a.frame_size != b.frame_size) {
491 		return false;
492 	}
493 	if (a.forward_history != 0 && b.forward_history != 0
494 		&& a.forward_history != b.forward_history) {
495 		return false;
496 	}
497 	if (a.backward_history != 0 && b.backward_history != 0
498 		&& a.backward_history != b.backward_history) {
499 		return false;
500 	}
501 
502 	if (a.encoding == 0 && b.encoding == 0)
503 		return true; // can't compare
504 
505 	switch((a.encoding != 0) ? a.encoding : b.encoding) {
506 		case media_encoded_video_format::B_ANY:
507 		default:
508 			return true;
509 	}
510 }
511 
512 
513 // #pragma mark - media_format::SpecializeTo() support
514 
515 
516 static void
517 raw_audio_format_specialize(media_raw_audio_format* format,
518 	const media_raw_audio_format* other)
519 {
520 	if (format->frame_rate == 0)
521 		format->frame_rate = other->frame_rate;
522 	if (format->channel_count == 0)
523 		format->channel_count = other->channel_count;
524 	if (format->format == 0)
525 		format->format = other->format;
526 	if (format->byte_order == 0)
527 		format->byte_order = other->byte_order;
528 	if (format->buffer_size == 0)
529 		format->buffer_size = other->buffer_size;
530 	if (format->frame_rate == 0)
531 		format->frame_rate = other->frame_rate;
532 }
533 
534 
535 static void
536 multi_audio_info_specialize(media_multi_audio_info* format,
537 	const media_multi_audio_info* other)
538 {
539 	if (format->channel_mask == 0)
540 		format->channel_mask = other->channel_mask;
541 	if (format->valid_bits == 0)
542 		format->valid_bits = other->valid_bits;
543 	if (format->matrix_mask == 0)
544 		format->matrix_mask = other->matrix_mask;
545 }
546 
547 
548 static void
549 multi_audio_format_specialize(media_multi_audio_format* format,
550 	const media_multi_audio_format* other)
551 {
552 	raw_audio_format_specialize(format, other);
553 	multi_audio_info_specialize(format, other);
554 }
555 
556 
557 static void
558 raw_video_format_specialize(media_raw_video_format* format,
559 	const media_raw_video_format* other)
560 {
561 	if (format->field_rate == 0)
562 		format->field_rate = other->field_rate;
563 	if (format->interlace == 0)
564 		format->interlace = other->interlace;
565 	if (format->first_active == 0)
566 		format->first_active = other->first_active;
567 	if (format->last_active == 0)
568 		format->last_active = other->last_active;
569 	if (format->orientation == 0)
570 		format->orientation = other->orientation;
571 	if (format->pixel_width_aspect == 0)
572 		format->pixel_width_aspect = other->pixel_width_aspect;
573 	if (format->pixel_height_aspect == 0)
574 		format->pixel_height_aspect = other->pixel_height_aspect;
575 	if (format->display.format == 0)
576 		format->display.format = other->display.format;
577 	if (format->display.line_width == 0)
578 		format->display.line_width = other->display.line_width;
579 	if (format->display.line_count == 0)
580 		format->display.line_count = other->display.line_count;
581 	if (format->display.bytes_per_row == 0)
582 		format->display.bytes_per_row = other->display.bytes_per_row;
583 	if (format->display.pixel_offset == 0)
584 		format->display.pixel_offset = other->display.pixel_offset;
585 	if (format->display.line_offset == 0)
586 		format->display.line_offset = other->display.line_offset;
587 	if (format->display.flags == 0)
588 		format->display.flags = other->display.flags;
589 }
590 
591 
592 static void
593 multistream_format_specialize(media_multistream_format* format,
594 	const media_multistream_format* other)
595 {
596 	if (format->avg_bit_rate == 0)
597 		format->avg_bit_rate = other->avg_bit_rate;
598 	if (format->max_bit_rate == 0)
599 		format->max_bit_rate = other->max_bit_rate;
600 	if (format->avg_chunk_size == 0)
601 		format->avg_chunk_size = other->avg_chunk_size;
602 	if (format->max_chunk_size == 0)
603 		format->max_chunk_size = other->max_chunk_size;
604 	if (format->flags == 0)
605 		format->flags = other->flags;
606 	if (format->format == 0)
607 		format->format = other->format;
608 
609 	switch (format->format) {
610 		case media_multistream_format::B_VID:
611 			if (format->u.vid.frame_rate == 0)
612 				format->u.vid.frame_rate = other->u.vid.frame_rate;
613 			if (format->u.vid.width == 0)
614 				format->u.vid.width = other->u.vid.width;
615 			if (format->u.vid.height == 0)
616 				format->u.vid.height = other->u.vid.height;
617 			if (format->u.vid.space == 0)
618 				format->u.vid.space = other->u.vid.space;
619 			if (format->u.vid.sampling_rate == 0)
620 				format->u.vid.sampling_rate = other->u.vid.sampling_rate;
621 			if (format->u.vid.sample_format == 0)
622 				format->u.vid.sample_format = other->u.vid.sample_format;
623 			if (format->u.vid.byte_order == 0)
624 				format->u.vid.byte_order = other->u.vid.byte_order;
625 			if (format->u.vid.channel_count == 0)
626 				format->u.vid.channel_count = other->u.vid.channel_count;
627 			break;
628 
629 		case media_multistream_format::B_AVI:
630 			if (format->u.avi.us_per_frame == 0)
631 				format->u.avi.us_per_frame = other->u.avi.us_per_frame;
632 			if (format->u.avi.width == 0)
633 				format->u.avi.width = other->u.avi.width;
634 			if (format->u.avi.height == 0)
635 				format->u.avi.height = other->u.avi.height;
636 			if (format->u.avi.type_count == 0)
637 				format->u.avi.type_count = other->u.avi.type_count;
638 			if (format->u.avi.types[0] == 0)
639 				format->u.avi.types[0] = other->u.avi.types[0];
640 			if (format->u.avi.types[1] == 0)
641 				format->u.avi.types[1] = other->u.avi.types[1];
642 			if (format->u.avi.types[2] == 0)
643 				format->u.avi.types[2] = other->u.avi.types[2];
644 			if (format->u.avi.types[3] == 0)
645 				format->u.avi.types[3] = other->u.avi.types[3];
646 			if (format->u.avi.types[4] == 0)
647 				format->u.avi.types[4] = other->u.avi.types[4];
648 			break;
649 
650 		default:
651 			ERROR("media_format::SpecializeTo can't specialize "
652 				"media_multistream_format of format %" B_PRId32 "\n",
653 				format->format);
654 	}
655 }
656 
657 
658 static void
659 encoded_audio_format_specialize(media_encoded_audio_format* format,
660 	const media_encoded_audio_format* other)
661 {
662 	raw_audio_format_specialize(&format->output, &other->output);
663 	if (format->encoding == 0)
664 		format->encoding = other->encoding;
665 	if (format->bit_rate == 0)
666 		format->bit_rate = other->bit_rate;
667 	if (format->frame_size == 0)
668 		format->frame_size = other->frame_size;
669 	multi_audio_info_specialize(&format->multi_info, &other->multi_info);
670 }
671 
672 
673 static void
674 encoded_video_format_specialize(media_encoded_video_format* format,
675 	const media_encoded_video_format* other)
676 {
677 	raw_video_format_specialize(&format->output, &other->output);
678 	if (format->avg_bit_rate == 0)
679 		format->avg_bit_rate = other->avg_bit_rate;
680 	if (format->max_bit_rate == 0)
681 		format->max_bit_rate = other->max_bit_rate;
682 	if (format->encoding == 0)
683 		format->encoding = other->encoding;
684 	if (format->frame_size == 0)
685 		format->frame_size = other->frame_size;
686 	if (format->forward_history == 0)
687 		format->forward_history = other->forward_history;
688 	if (format->backward_history == 0)
689 		format->backward_history = other->backward_history;
690 }
691 
692 
693 // #pragma mark - media_format
694 
695 
696 bool
697 media_format::Matches(const media_format* other) const
698 {
699 	CALLED();
700 
701 	if (type == 0 && other->type == 0) {
702 		// TODO: How do we compare two formats with no type?
703 		return true;
704 	}
705 
706 	if (type != 0 && other->type != 0 && type != other->type)
707 		return false;
708 
709 	switch ((type != 0) ? type : other->type) {
710 		case B_MEDIA_RAW_AUDIO:
711 			return multi_audio_format_matches(u.raw_audio, other->u.raw_audio);
712 
713 		case B_MEDIA_RAW_VIDEO:
714 			return raw_video_format_matches(u.raw_video, other->u.raw_video);
715 
716 		case B_MEDIA_MULTISTREAM:
717 			return multistream_format_matches(u.multistream,
718 				other->u.multistream);
719 
720 		case B_MEDIA_ENCODED_AUDIO:
721 			return encoded_audio_format_matches(u.encoded_audio,
722 				other->u.encoded_audio);
723 
724 		case B_MEDIA_ENCODED_VIDEO:
725 			return encoded_video_format_matches(u.encoded_video,
726 				other->u.encoded_video);
727 
728 		default:
729 			return true; // TODO: really?
730 	}
731 }
732 
733 
734 void
735 media_format::SpecializeTo(const media_format* otherFormat)
736 {
737 	CALLED();
738 
739 	if (type == 0 && otherFormat->type == 0) {
740 		ERROR("media_format::SpecializeTo can't specialize wildcard to other "
741 			"wildcard format\n");
742 		return;
743 	}
744 
745 	if (type == 0)
746 		type = otherFormat->type;
747 
748 	switch (type) {
749 		case B_MEDIA_RAW_AUDIO:
750 			multi_audio_format_specialize(&u.raw_audio,
751 				&otherFormat->u.raw_audio);
752 			return;
753 
754 		case B_MEDIA_RAW_VIDEO:
755 			raw_video_format_specialize(&u.raw_video,
756 				&otherFormat->u.raw_video);
757 			return;
758 
759 		case B_MEDIA_MULTISTREAM:
760 			multistream_format_specialize(&u.multistream,
761 				&otherFormat->u.multistream);
762 			return;
763 
764 		case B_MEDIA_ENCODED_AUDIO:
765 			encoded_audio_format_specialize(&u.encoded_audio,
766 				&otherFormat->u.encoded_audio);
767 			return;
768 
769 		case B_MEDIA_ENCODED_VIDEO:
770 			encoded_video_format_specialize(&u.encoded_video,
771 				&otherFormat->u.encoded_video);
772 			return;
773 
774 		default:
775 			ERROR("media_format::SpecializeTo can't specialize format "
776 				"type %d\n", type);
777 	}
778 }
779 
780 
781 status_t
782 media_format::SetMetaData(const void* data, size_t size)
783 {
784 	if (!data || size < 0 || size > META_DATA_MAX_SIZE)
785 		return B_BAD_VALUE;
786 
787 	void* new_addr;
788 	area_id new_area;
789 	if (size < META_DATA_AREA_MIN_SIZE) {
790 		new_area = B_BAD_VALUE;
791 		new_addr = malloc(size);
792 		if (!new_addr)
793 			return B_NO_MEMORY;
794 	} else {
795 		new_area = create_area("meta_data_area", &new_addr, B_ANY_ADDRESS,
796 			ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
797 		if (new_area < 0)
798 			return (status_t)new_area;
799 	}
800 
801 	if (meta_data_area > 0)
802 		delete_area(meta_data_area);
803 	else
804 		free(meta_data);
805 
806 	meta_data = new_addr;
807 	meta_data_size = size;
808 	meta_data_area = new_area;
809 
810 	memcpy(meta_data, data, size);
811 
812 	if (meta_data_area > 0)
813 		set_area_protection(meta_data_area, B_READ_AREA);
814 
815 	return B_OK;
816 }
817 
818 
819 const void*
820 media_format::MetaData() const
821 {
822 	return meta_data;
823 }
824 
825 
826 int32
827 media_format::MetaDataSize() const
828 {
829 	return meta_data_size;
830 }
831 
832 
833 media_format::media_format()
834 {
835 	memset(this, 0x00, sizeof(*this));
836 	meta_data_area = B_BAD_VALUE;
837 }
838 
839 
840 media_format::media_format(const media_format& other)
841 {
842 	memset(this, 0x00, sizeof(*this));
843 	meta_data_area = B_BAD_VALUE;
844 	*this = other;
845 }
846 
847 
848 media_format::~media_format()
849 {
850 	if (meta_data_area > 0)
851 		delete_area(meta_data_area);
852 	else
853 		free(meta_data);
854 }
855 
856 
857 // final
858 media_format&
859 media_format::operator=(const media_format& clone)
860 {
861 	// get rid of this format's meta data
862 	this->~media_format();
863 		// danger: using only ~media_format() would call the constructor
864 
865 	// make a binary copy
866 	memcpy(this, &clone, sizeof(*this));
867 	// some binary copies are invalid:
868 	meta_data = NULL;
869 	meta_data_area = B_BAD_VALUE;
870 
871 	// clone or copy the meta data
872 	if (clone.meta_data) {
873 		if (clone.meta_data_area != B_BAD_VALUE) {
874 			meta_data_area = clone_area("meta_data_clone_area", &meta_data,
875 				B_ANY_ADDRESS, B_READ_AREA, clone.meta_data_area);
876 			if (meta_data_area < 0) {
877 				// whoops, we just lost our meta data
878 				meta_data = NULL;
879 				meta_data_size = 0;
880 			}
881 		} else {
882 			meta_data = malloc(meta_data_size);
883 			if (meta_data) {
884 				memcpy(meta_data, clone.meta_data, meta_data_size);
885 			} else {
886 				// whoops, we just lost our meta data
887 				meta_data_size = 0;
888 			}
889 		}
890 	}
891 	return *this;
892 }
893 
894 
895 // #pragma mark -
896 
897 
898 bool
899 operator==(const media_raw_audio_format& a, const media_raw_audio_format& b)
900 {
901 	return a.frame_rate == b.frame_rate
902 		&& a.channel_count == b.channel_count
903 		&& a.format == b.format
904 		&& a.byte_order == b.byte_order
905 		&& a.buffer_size == b.buffer_size;
906 }
907 
908 
909 bool
910 operator==(const media_multi_audio_info& a, const media_multi_audio_info& b)
911 {
912 	return a.channel_mask == b.channel_mask
913 		&& a.valid_bits == b.valid_bits
914 		&& a.matrix_mask == b.matrix_mask;
915 }
916 
917 
918 bool
919 operator==(const media_multi_audio_format& a,
920 	const media_multi_audio_format& b)
921 {
922 	return (media_raw_audio_format)a == (media_raw_audio_format)b
923 		&& (media_multi_audio_info)a == (media_multi_audio_info)b;
924 }
925 
926 
927 bool
928 operator==(const media_encoded_audio_format& a,
929 	const media_encoded_audio_format& b)
930 {
931 	return a.output == b.output
932 		&& a.encoding == b.encoding
933 		&& a.bit_rate == b.bit_rate
934 		&& a.frame_size == b.frame_size
935 		&& a.multi_info == b.multi_info;
936 }
937 
938 
939 bool
940 operator==(const media_video_display_info& a,
941 	const media_video_display_info& b)
942 {
943 	return a.format == b.format
944 		&& a.line_width == b.line_width
945 		&& a.line_count == b.line_count
946 		&& a.bytes_per_row == b.bytes_per_row
947 		&& a.pixel_offset == b.pixel_offset
948 		&& a.line_offset == b.line_offset
949 		&& a.flags == b.flags;
950 }
951 
952 
953 bool
954 operator==(const media_raw_video_format& a, const media_raw_video_format& b)
955 {
956 	return a.field_rate == b.field_rate
957 		&& a.interlace == b.interlace
958 		&& a.first_active == b.first_active
959 		&& a.last_active == b.last_active
960 		&& a.orientation == b.orientation
961 		&& a.pixel_width_aspect == b.pixel_width_aspect
962 		&& a.pixel_height_aspect == b.pixel_height_aspect
963 		&& a.display == b.display;
964 }
965 
966 
967 bool
968 operator==(const media_encoded_video_format& a,
969 	const media_encoded_video_format& b)
970 {
971 	return a.output == b.output
972 		&& a.avg_bit_rate == b.avg_bit_rate
973 		&& a.max_bit_rate == b.max_bit_rate
974 		&& a.encoding == b.encoding
975 		&& a.frame_size == b.frame_size
976 		&& a.forward_history == b.forward_history
977 		&& a.backward_history == b.backward_history;
978 }
979 
980 
981 bool
982 operator==(const media_multistream_format::vid_info& a,
983 	const media_multistream_format::vid_info& b)
984 {
985 	return a.frame_rate == b.frame_rate
986 		&& a.width == b.width
987 		&& a.height == b.height
988 		&& a.space == b.space
989 		&& a.sampling_rate == b.sampling_rate
990 		&& a.sample_format == b.sample_format
991 		&& a.byte_order == b.byte_order
992 		&& a.channel_count == b.channel_count;
993 }
994 
995 
996 bool
997 operator==(const media_multistream_format::avi_info& a,
998 	const media_multistream_format::avi_info& b)
999 {
1000 	return a.us_per_frame == b.us_per_frame
1001 		&& a.width == b.width
1002 		&& a.height == b.height
1003 		&& a.type_count == b.type_count
1004 		&& a.types[0] == b.types[0]
1005 		&& a.types[1] == b.types[1]
1006 		&& a.types[2] == b.types[2]
1007 		&& a.types[3] == b.types[3]
1008 		&& a.types[4] == b.types[4];
1009 }
1010 
1011 
1012 bool
1013 operator==(const media_multistream_format& a,
1014 	const media_multistream_format& b)
1015 {
1016 	if (a.avg_bit_rate != b.avg_bit_rate
1017 		|| a.max_bit_rate != b.max_bit_rate
1018 		|| a.avg_chunk_size != b.avg_chunk_size
1019 		|| a.max_chunk_size != b.max_chunk_size
1020 		|| a.format != b.format
1021 		|| a.flags != b.flags) {
1022 		return false;
1023 	}
1024 
1025 	switch (a.format) {
1026 		case media_multistream_format::B_VID:
1027 			return a.u.vid == b.u.vid;
1028 
1029 		case media_multistream_format::B_AVI:
1030 			return a.u.avi == b.u.avi;
1031 
1032 		default:
1033 			return true; // TODO: really?
1034 	}
1035 }
1036 
1037 
1038 bool
1039 operator==(const media_format& a, const media_format& b)
1040 {
1041 	if (a.type != b.type
1042 		|| a.user_data_type != b.user_data_type
1043 		// TODO: compare user_data[48] ?
1044 		|| a.require_flags != b.require_flags
1045 		|| a.deny_flags != b.deny_flags) {
1046 		return false;
1047 	}
1048 
1049 	switch (a.type) {
1050 		case B_MEDIA_RAW_AUDIO:
1051 			return a.u.raw_audio == b.u.raw_audio;
1052 
1053 		case B_MEDIA_RAW_VIDEO:
1054 			return a.u.raw_video == b.u.raw_video;
1055 
1056 		case B_MEDIA_MULTISTREAM:
1057 			return a.u.multistream == b.u.multistream;
1058 
1059 		case B_MEDIA_ENCODED_AUDIO:
1060 			return a.u.encoded_audio == b.u.encoded_audio;
1061 
1062 		case B_MEDIA_ENCODED_VIDEO:
1063 			return a.u.encoded_video == b.u.encoded_video;
1064 
1065 		default:
1066 			return true; // TODO: really?
1067 	}
1068 }
1069 
1070 
1071 // #pragma mark -
1072 
1073 
1074 /*! return \c true if a and b are compatible (accounting for wildcards)
1075 	a is the format you want to feed to something accepting b
1076 */
1077 bool
1078 format_is_compatible(const media_format& a, const media_format& b)
1079 {
1080 	return a.Matches(&b);
1081 }
1082 
1083 
1084 bool
1085 string_for_format(const media_format& f, char* buf, size_t size)
1086 {
1087 	char encoding[10]; /* maybe Be wanted to use some 4CCs ? */
1088 	const char* videoOrientation = "0"; /* I'd use "NC", R5 uses 0. */
1089 
1090 	if (buf == NULL)
1091 		return false;
1092 	switch (f.type) {
1093 	case B_MEDIA_RAW_AUDIO:
1094 		snprintf(buf, size,
1095 			"raw_audio;%g;%" B_PRIu32 ";0x%" B_PRIx32 ";%" B_PRIu32 ";0x%"
1096 				B_PRIxSIZE ";0x%#" B_PRIx32 ";%d;0x%04x",
1097 			f.u.raw_audio.frame_rate,
1098 			f.u.raw_audio.channel_count,
1099 			f.u.raw_audio.format,
1100 			f.u.raw_audio.byte_order,
1101 			f.u.raw_audio.buffer_size,
1102 			f.u.raw_audio.channel_mask,
1103 			f.u.raw_audio.valid_bits,
1104 			f.u.raw_audio.matrix_mask);
1105 		return true;
1106 	case B_MEDIA_RAW_VIDEO:
1107 		if (f.u.raw_video.orientation == B_VIDEO_TOP_LEFT_RIGHT)
1108 			videoOrientation = "TopLR";
1109 		else if (f.u.raw_video.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT)
1110 			videoOrientation = "BotLR";
1111 		snprintf(buf, size, "raw_video;%g;0x%x;%" B_PRIu32 ";%" B_PRIu32 ";%"
1112 				B_PRIu32 ";%" B_PRIu32 ";%s;%d;%d",
1113 			f.u.raw_video.field_rate,
1114 			f.u.raw_video.display.format,
1115 			f.u.raw_video.interlace,
1116 			f.u.raw_video.display.line_width,
1117 			f.u.raw_video.display.line_count,
1118 			f.u.raw_video.first_active,
1119 			videoOrientation,
1120 			f.u.raw_video.pixel_width_aspect,
1121 			f.u.raw_video.pixel_height_aspect);
1122 		return true;
1123 	case B_MEDIA_ENCODED_AUDIO:
1124 		snprintf(encoding, 10, "%d", f.u.encoded_audio.encoding);
1125 		snprintf(buf, size,
1126 			"caudio;%s;%g;%ld;(%g;%" B_PRIu32 ";0x%" B_PRIx32 ";%" B_PRIu32
1127 				";0x%" B_PRIxSIZE ";0x%08" B_PRIx32 ";%d;0x%04x)",
1128 			encoding,
1129 			f.u.encoded_audio.bit_rate,
1130 			f.u.encoded_audio.frame_size,
1131 			f.u.encoded_audio.output.frame_rate,
1132 			f.u.encoded_audio.output.channel_count,
1133 			f.u.encoded_audio.output.format,
1134 			f.u.encoded_audio.output.byte_order,
1135 			f.u.encoded_audio.output.buffer_size,
1136 			f.u.encoded_audio.multi_info.channel_mask,
1137 			f.u.encoded_audio.multi_info.valid_bits,
1138 			f.u.encoded_audio.multi_info.matrix_mask);
1139 		return true;
1140 	case B_MEDIA_ENCODED_VIDEO:
1141 		snprintf(encoding, 10, "%d", f.u.encoded_video.encoding);
1142 		if (f.u.encoded_video.output.orientation == B_VIDEO_TOP_LEFT_RIGHT)
1143 			videoOrientation = "TopLR";
1144 		else if (f.u.encoded_video.output.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT)
1145 			videoOrientation = "BotLR";
1146 		snprintf(buf, size,
1147 			"cvideo;%s;%g;%g;%" B_PRIuSIZE ";(%g;0x%x;%" B_PRIu32 ";%" B_PRIu32
1148 				";%" B_PRIu32 ";%" B_PRIu32 ";%s;%d;%d)",
1149 			encoding,
1150 			f.u.encoded_video.avg_bit_rate,
1151 			f.u.encoded_video.max_bit_rate,
1152 			f.u.encoded_video.frame_size,
1153 			f.u.encoded_video.output.field_rate,
1154 			f.u.encoded_video.output.display.format,
1155 			f.u.encoded_video.output.interlace,
1156 			f.u.encoded_video.output.display.line_width,
1157 			f.u.encoded_video.output.display.line_count,
1158 			f.u.encoded_video.output.first_active,
1159 			videoOrientation,
1160 			f.u.encoded_video.output.pixel_width_aspect,
1161 			f.u.encoded_video.output.pixel_height_aspect);
1162 		return true;
1163 	default:
1164 		snprintf(buf, size, "%d-", f.type);
1165 		unsigned char* p = (unsigned char*)&(f.u);
1166 		size -= strlen(buf);
1167 		buf += strlen(buf);
1168 		for (int i = 0; (size > 2) && (i < 96); i++) {
1169 			snprintf(buf, 3, "%2.2x", *(p + i));
1170 			buf+=2;
1171 			size-=2;
1172 		}
1173 		return true; // ?
1174 	}
1175 	return false;
1176 }
1177 
1178 
1179 // #pragma mark -
1180 
1181 
1182 bool
1183 operator==(const media_file_format_id& a, const media_file_format_id& b)
1184 {
1185 	return a.node == b.node && a.device == b.device
1186 		&& a.internal_id == b.internal_id;
1187 }
1188 
1189 
1190 bool
1191 operator<(const media_file_format_id& a, const media_file_format_id& b)
1192 {
1193 	return a.internal_id < b.internal_id;
1194 }
1195 
1196 
1197 // #pragma mark -
1198 
1199 
1200 //! Use this function to iterate through available file format writers.
1201 status_t
1202 get_next_file_format(int32* cookie, media_file_format* mff)
1203 {
1204 	if (cookie == NULL || mff == NULL)
1205 		return B_BAD_VALUE;
1206 
1207 	status_t ret = AddOnManager::GetInstance()->GetFileFormat(mff, *cookie);
1208 	if (ret != B_OK)
1209 		return ret;
1210 
1211 	*cookie = *cookie + 1;
1212 
1213 	return B_OK;
1214 }
1215 
1216 
1217 // #pragma mark -
1218 
1219 
1220 // final & verified
1221 const char* B_MEDIA_SERVER_SIGNATURE = "application/x-vnd.Be.media-server";
1222 const char* B_MEDIA_ADDON_SERVER_SIGNATURE = "application/x-vnd.Be.addon-host";
1223 
1224 const type_code B_CODEC_TYPE_INFO = 0x040807b2;
1225 
1226 
1227 // #pragma mark -
1228 
1229 
1230 // shutdown_media_server() and launch_media_server()
1231 // are provided by libbe.so in BeOS R5
1232 
1233 #define MEDIA_SERVICE_NOTIFICATION_ID "MediaServiceNotificationID"
1234 
1235 
1236 void
1237 notify_system(float progress, const char* message)
1238 {
1239 	BNotification notification(B_PROGRESS_NOTIFICATION);
1240 	notification.SetMessageID(MEDIA_SERVICE_NOTIFICATION_ID);
1241 	notification.SetProgress(progress);
1242 	notification.SetGroup(B_TRANSLATE("Media Service"));
1243 	notification.SetContent(message);
1244 
1245 	app_info info;
1246 	be_app->GetAppInfo(&info);
1247 	BBitmap icon(BRect(0, 0, 32, 32), B_RGBA32);
1248 	BNode node(&info.ref);
1249 	BIconUtils::GetVectorIcon(&node, "BEOS:ICON", &icon);
1250 	notification.SetIcon(&icon);
1251 
1252 	notification.Send();
1253 }
1254 
1255 
1256 void
1257 progress_shutdown(int stage,
1258 	bool (*progress)(int stage, const char* message, void* cookie),
1259 	void* cookie)
1260 {
1261 	// parameter "message" is no longer used. It is kept for compatibility with
1262 	// BeOS as this is used as a shutdown_media_server callback.
1263 
1264 	TRACE("stage: %i\n", stage);
1265 	const char* string = "Unknown stage";
1266 	switch (stage) {
1267 		case 10:
1268 			string = B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS);
1269 			break;
1270 		case 20:
1271 			string = B_TRANSLATE("Telling media_addon_server to quit.");
1272 			break;
1273 		case 40:
1274 			string = B_TRANSLATE("Waiting for media_server to quit.");
1275 			break;
1276 		case 50:
1277 			string = B_TRANSLATE("Waiting for media_server to quit.");
1278 			break;
1279 		case 70:
1280 			string = B_TRANSLATE("Cleaning up.");
1281 			break;
1282 		case 100:
1283 			string = B_TRANSLATE("Done shutting down.");
1284 			break;
1285 	}
1286 
1287 	if (progress == NULL)
1288 		notify_system(stage / 100.0f, string);
1289 	else
1290 		progress(stage, string, cookie);
1291 }
1292 
1293 
1294 status_t
1295 shutdown_media_server(bigtime_t timeout,
1296 	bool (*progress)(int stage, const char* message, void* cookie),
1297 	void* cookie)
1298 {
1299 	BMessage msg(B_QUIT_REQUESTED);
1300 	BMessage reply;
1301 	status_t err;
1302 
1303 	if ((err = msg.AddBool("be:_user_request", true)) != B_OK)
1304 		return err;
1305 
1306 	if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
1307 		BMessenger messenger(B_MEDIA_SERVER_SIGNATURE);
1308 		progress_shutdown(10, progress, cookie);
1309 
1310 		err = messenger.SendMessage(&msg, &reply, 2000000, 2000000);
1311 		if (err != B_OK)
1312 			return err;
1313 
1314 		int32 rv;
1315 		if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK)
1316 			return rv;
1317 	}
1318 
1319 	if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
1320 		BMessenger messenger(B_MEDIA_ADDON_SERVER_SIGNATURE);
1321 		progress_shutdown(20, progress, cookie);
1322 
1323 		err = messenger.SendMessage(&msg, &reply, 2000000, 2000000);
1324 		if (err != B_OK)
1325 			return err;
1326 
1327 		int32 rv;
1328 		if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK)
1329 			return rv;
1330 	}
1331 
1332 	if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
1333 		progress_shutdown(40, progress, cookie);
1334 		snooze(200000);
1335 	}
1336 
1337 	if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
1338 		progress_shutdown(50, progress, cookie);
1339 		snooze(200000);
1340 	}
1341 
1342 	progress_shutdown(70, progress, cookie);
1343 	snooze(1000000);
1344 
1345 	if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
1346 		kill_team(be_roster->TeamFor(B_MEDIA_SERVER_SIGNATURE));
1347 	}
1348 
1349 	if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
1350 		kill_team(be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE));
1351 	}
1352 
1353 	progress_shutdown(100, progress, cookie);
1354 	snooze(1000000);
1355 
1356 	return B_OK;
1357 }
1358 
1359 
1360 void
1361 progress_startup(int stage,
1362 	bool (*progress)(int stage, const char* message, void* cookie),
1363 	void* cookie)
1364 {
1365 	// parameter "message" is no longer used. It is kept for compatibility with
1366 	// BeOS as this is used as a shutdown_media_server callback.
1367 
1368 	TRACE("stage: %i\n", stage);
1369 	const char* string = "Unknown stage";
1370 	switch (stage) {
1371 		case 10:
1372 			string = B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS);
1373 			break;
1374 		case 20:
1375 			string = B_TRANSLATE("Stopping media_addon_server.");
1376 			break;
1377 		case 50:
1378 			string = B_TRANSLATE("Starting media_services.");
1379 			break;
1380 		case 90:
1381 			string = B_TRANSLATE("Error occurred starting media services.");
1382 			break;
1383 		case 100:
1384 			string = B_TRANSLATE("Ready for use.");
1385 			break;
1386 	}
1387 
1388 	if (progress == NULL)
1389 		notify_system(stage / 100.0f, string);
1390 	else
1391 		progress(stage, string, cookie);
1392 }
1393 
1394 
1395 status_t
1396 launch_media_server(uint32 flags)
1397 {
1398 	return launch_media_server(0, NULL, NULL, flags);
1399 }
1400 
1401 
1402 status_t
1403 launch_media_server(bigtime_t timeout,
1404 	bool (*progress)(int stage, const char* message, void* cookie),
1405 	void* cookie, uint32 flags)
1406 {
1407 	if (BMediaRoster::IsRunning())
1408 		return B_ALREADY_RUNNING;
1409 
1410 	// The media_server crashed
1411 	if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
1412 		progress_startup(10, progress, cookie);
1413 		kill_team(be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE));
1414 		snooze(1000000);
1415 	}
1416 
1417 	// The media_addon_server crashed
1418 	if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
1419 		progress_startup(20, progress, cookie);
1420 		kill_team(be_roster->TeamFor(B_MEDIA_SERVER_SIGNATURE));
1421 		snooze(1000000);
1422 	}
1423 
1424 	progress_startup(50, progress, cookie);
1425 
1426 	status_t err = be_roster->Launch(B_MEDIA_SERVER_SIGNATURE);
1427 	if (err != B_OK)
1428 		return err;
1429 
1430 	err = B_MEDIA_SYSTEM_FAILURE;
1431 	for (int i = 0; i < 15; i++) {
1432 		snooze(2000000);
1433 
1434 		BMessage msg(1); // this is a hack
1435 		BMessage reply;
1436 		BMessenger messenger(B_MEDIA_ADDON_SERVER_SIGNATURE);
1437 
1438 		if (messenger.IsValid()) {
1439 			messenger.SendMessage(&msg, &reply, 2000000, 2000000);
1440 			err = B_OK;
1441 			progress_startup(100, progress, cookie);
1442 			break;
1443 		}
1444 	}
1445 
1446 	if (err != B_OK)
1447 		progress_startup(90, progress, cookie);
1448 
1449 	return err;
1450 }
1451 
1452 
1453 // #pragma mark -
1454 
1455 
1456 //	Given an image_id, prepare that image_id for realtime media
1457 //	If the kind of media indicated by "flags" is not enabled for real-time,
1458 //	B_MEDIA_REALTIME_DISABLED is returned.
1459 //	If there are not enough system resources to enable real-time performance,
1460 //	B_MEDIA_REALTIME_UNAVAILABLE is returned.
1461 status_t
1462 media_realtime_init_image(image_id image, uint32 flags)
1463 {
1464 	UNIMPLEMENTED();
1465 	return B_OK;
1466 }
1467 
1468 //	Given a thread ID, and an optional indication of what the thread is
1469 //	doing in "flags", prepare the thread for real-time media performance.
1470 //	Currently, this means locking the thread stack, up to size_used bytes,
1471 //	or all of it if 0 is passed. Typically, you will not be using all
1472 //	256 kB of the stack, so you should pass some smaller value you determine
1473 //	from profiling the thread; typically in the 32-64kB range.
1474 //	Return values are the same as for media_prepare_realtime_image().
1475 status_t
1476 media_realtime_init_thread(thread_id thread, size_t stack_used, uint32 flags)
1477 {
1478 	UNIMPLEMENTED();
1479 	return B_OK;
1480 }
1481 
1482 
1483 // #pragma mark - media_encode_info
1484 
1485 
1486 media_encode_info::media_encode_info()
1487 {
1488 	flags = 0;
1489 	used_data_size = 0;
1490 	start_time = 0;
1491 	time_to_encode = INT64_MAX;
1492 	file_format_data = NULL;
1493 	file_format_data_size = 0;
1494 	codec_data = NULL;
1495 	codec_data_size = 0;
1496 }
1497 
1498 
1499 media_decode_info::media_decode_info()
1500 {
1501 	time_to_decode = INT64_MAX;
1502 	file_format_data = NULL;
1503 	file_format_data_size = 0;
1504 	codec_data = NULL;
1505 	codec_data_size = 0;
1506 }
1507 
1508 
1509