1504 lines
36 KiB
C++
1504 lines
36 KiB
C++
/*
|
|
* Copyright 2015, Dario Casalinuovo
|
|
* Copyright 2004, 2006, Jérôme Duval.
|
|
* Copyright 2003-2004, Andrew Bachmann.
|
|
* Copyright 2002-2004, 2006 Marcus Overhagen.
|
|
* Copyright 2002, Eric Jaessler.
|
|
* All rights reserved. Distributed under the terms of the MIT license.
|
|
*/
|
|
|
|
|
|
#include <MediaDefs.h>
|
|
|
|
#include <Application.h>
|
|
#include <Bitmap.h>
|
|
#include <Catalog.h>
|
|
#include <IconUtils.h>
|
|
#include <LaunchRoster.h>
|
|
#include <Locale.h>
|
|
#include <MediaNode.h>
|
|
#include <MediaRoster.h>
|
|
#include <Node.h>
|
|
#include <Notification.h>
|
|
#include <Roster.h>
|
|
|
|
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "AddOnManager.h"
|
|
#include "DataExchange.h"
|
|
#include "MediaDebug.h"
|
|
#include "MediaMisc.h"
|
|
#include "MediaRosterEx.h"
|
|
|
|
|
|
#define META_DATA_MAX_SIZE (16 << 20)
|
|
#define META_DATA_AREA_MIN_SIZE 32000
|
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
#define B_TRANSLATION_CONTEXT "MediaDefs"
|
|
|
|
|
|
// #pragma mark - media_destination
|
|
|
|
|
|
media_destination::media_destination(port_id port, int32 id)
|
|
:
|
|
port(port),
|
|
id(id)
|
|
{
|
|
}
|
|
|
|
|
|
media_destination::media_destination(const media_destination& clone)
|
|
:
|
|
port(clone.port),
|
|
id(clone.id)
|
|
{
|
|
}
|
|
|
|
|
|
media_destination&
|
|
media_destination::operator=(const media_destination& clone)
|
|
{
|
|
port = clone.port;
|
|
id = clone.id;
|
|
return *this;
|
|
}
|
|
|
|
|
|
media_destination::media_destination()
|
|
:
|
|
port(-1),
|
|
id(-1)
|
|
{
|
|
}
|
|
|
|
|
|
media_destination::~media_destination()
|
|
{
|
|
}
|
|
|
|
|
|
media_destination media_destination::null(-1, -1);
|
|
|
|
|
|
// #pragma mark - media_source
|
|
|
|
|
|
media_source::media_source(port_id port,
|
|
int32 id)
|
|
:
|
|
port(port),
|
|
id(id)
|
|
{
|
|
}
|
|
|
|
|
|
media_source::media_source(const media_source& clone)
|
|
:
|
|
port(clone.port),
|
|
id(clone.id)
|
|
{
|
|
}
|
|
|
|
|
|
media_source&
|
|
media_source::operator=(const media_source& clone)
|
|
{
|
|
port = clone.port;
|
|
id = clone.id;
|
|
return *this;
|
|
}
|
|
|
|
|
|
media_source::media_source()
|
|
:
|
|
port(-1),
|
|
id(-1)
|
|
{
|
|
}
|
|
|
|
|
|
media_source::~media_source()
|
|
{
|
|
}
|
|
|
|
|
|
media_source media_source::null(-1, -1);
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
bool
|
|
operator==(const media_destination& a, const media_destination& b)
|
|
{
|
|
return a.port == b.port && a.id == b.id;
|
|
}
|
|
|
|
|
|
bool
|
|
operator!=(const media_destination& a, const media_destination& b)
|
|
{
|
|
return a.port != b.port || a.id != b.id;
|
|
}
|
|
|
|
|
|
bool
|
|
operator<(const media_destination& a, const media_destination& b)
|
|
{
|
|
UNIMPLEMENTED();
|
|
return false;
|
|
}
|
|
|
|
|
|
bool
|
|
operator==(const media_source& a, const media_source& b)
|
|
{
|
|
return a.port == b.port && a.id == b.id;
|
|
}
|
|
|
|
|
|
bool
|
|
operator!=(const media_source& a, const media_source& b)
|
|
{
|
|
return a.port != b.port || a.id != b.id;
|
|
}
|
|
|
|
|
|
bool
|
|
operator<(const media_source& a, const media_source& b)
|
|
{
|
|
UNIMPLEMENTED();
|
|
return false;
|
|
}
|
|
|
|
|
|
bool
|
|
operator==(const media_node& a, const media_node& b)
|
|
{
|
|
return a.node == b.node && a.port == b.port && a.kind == b.kind;
|
|
}
|
|
|
|
|
|
bool
|
|
operator!=(const media_node& a, const media_node& b)
|
|
{
|
|
return a.node != b.node || a.port != b.port || a.kind != b.kind;
|
|
}
|
|
|
|
|
|
bool
|
|
operator<(const media_node& a, const media_node& b)
|
|
{
|
|
UNIMPLEMENTED();
|
|
return false;
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
#if __GNUC__ == 2
|
|
const media_multi_audio_format media_raw_audio_format::wildcard
|
|
= media_multi_audio_format();
|
|
|
|
const media_multi_audio_format media_multi_audio_format::wildcard
|
|
= media_multi_audio_format();
|
|
#else
|
|
const media_multi_audio_format media_raw_audio_format::wildcard = {};
|
|
|
|
const media_multi_audio_format media_multi_audio_format::wildcard = {};
|
|
#endif
|
|
|
|
const media_encoded_audio_format media_encoded_audio_format::wildcard = {};
|
|
|
|
const media_video_display_info media_video_display_info::wildcard = {};
|
|
|
|
const media_raw_video_format media_raw_video_format::wildcard = {};
|
|
|
|
const media_encoded_video_format media_encoded_video_format::wildcard = {};
|
|
|
|
const media_multistream_format media_multistream_format::wildcard = {};
|
|
|
|
|
|
// #pragma mark - media_format::Matches() support
|
|
|
|
|
|
static bool
|
|
raw_audio_format_matches(const media_raw_audio_format& a,
|
|
const media_raw_audio_format& b)
|
|
{
|
|
if (a.frame_rate != 0 && b.frame_rate != 0 && a.frame_rate != b.frame_rate)
|
|
return false;
|
|
if (a.channel_count != 0 && b.channel_count != 0
|
|
&& a.channel_count != b.channel_count) {
|
|
return false;
|
|
}
|
|
if (a.format != 0 && b.format != 0 && a.format != b.format)
|
|
return false;
|
|
if (a.byte_order != 0 && b.byte_order != 0 && a.byte_order != b.byte_order)
|
|
return false;
|
|
if (a.buffer_size != 0 && b.buffer_size != 0
|
|
&& a.buffer_size != b.buffer_size) {
|
|
return false;
|
|
}
|
|
if (a.frame_rate != 0 && b.frame_rate != 0 && a.frame_rate != b.frame_rate)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
|
|
static bool
|
|
multi_audio_info_matches(const media_multi_audio_info& a,
|
|
const media_multi_audio_info& b)
|
|
{
|
|
if (a.channel_mask != 0 && b.channel_mask != 0
|
|
&& a.channel_mask != b.channel_mask) {
|
|
return false;
|
|
}
|
|
if (a.valid_bits != 0 && b.valid_bits != 0 && a.valid_bits != b.valid_bits)
|
|
return false;
|
|
if (a.matrix_mask != 0 && b.matrix_mask != 0
|
|
&& a.matrix_mask != b.matrix_mask) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
static bool
|
|
multi_audio_format_matches(const media_multi_audio_format& a,
|
|
const media_multi_audio_format& b)
|
|
{
|
|
return raw_audio_format_matches(a, b) && multi_audio_info_matches(a, b);
|
|
}
|
|
|
|
|
|
static bool
|
|
raw_video_format_matches(const media_raw_video_format& a,
|
|
const media_raw_video_format& b)
|
|
{
|
|
if (a.field_rate != 0 && b.field_rate != 0
|
|
&& a.field_rate != b.field_rate) {
|
|
return false;
|
|
}
|
|
if (a.interlace != 0 && b.interlace != 0
|
|
&& a.interlace != b.interlace) {
|
|
return false;
|
|
}
|
|
if (a.first_active != 0 && b.first_active != 0
|
|
&& a.first_active != b.first_active) {
|
|
return false;
|
|
}
|
|
if (a.last_active != 0 && b.last_active != 0
|
|
&& a.last_active != b.last_active) {
|
|
return false;
|
|
}
|
|
if (a.orientation != 0 && b.orientation != 0
|
|
&& a.orientation != b.orientation) {
|
|
return false;
|
|
}
|
|
if (a.pixel_width_aspect != 0 && b.pixel_width_aspect != 0
|
|
&& a.pixel_width_aspect != b.pixel_width_aspect) {
|
|
return false;
|
|
}
|
|
if (a.pixel_height_aspect != 0 && b.pixel_height_aspect != 0
|
|
&& a.pixel_height_aspect != b.pixel_height_aspect) {
|
|
return false;
|
|
}
|
|
if (a.display.format != 0 && b.display.format != 0
|
|
&& a.display.format != b.display.format) {
|
|
return false;
|
|
}
|
|
if (a.display.line_width != 0 && b.display.line_width != 0
|
|
&& a.display.line_width != b.display.line_width) {
|
|
return false;
|
|
}
|
|
if (a.display.line_count != 0 && b.display.line_count != 0
|
|
&& a.display.line_count != b.display.line_count) {
|
|
return false;
|
|
}
|
|
if (a.display.bytes_per_row != 0 && b.display.bytes_per_row != 0
|
|
&& a.display.bytes_per_row != b.display.bytes_per_row) {
|
|
return false;
|
|
}
|
|
if (a.display.pixel_offset != 0 && b.display.pixel_offset != 0
|
|
&& a.display.pixel_offset != b.display.pixel_offset) {
|
|
return false;
|
|
}
|
|
if (a.display.line_offset != 0 && b.display.line_offset != 0
|
|
&& a.display.line_offset != b.display.line_offset) {
|
|
return false;
|
|
}
|
|
if (a.display.flags != 0 && b.display.flags != 0
|
|
&& a.display.flags != b.display.flags) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
static bool
|
|
multistream_format_matches(const media_multistream_format& a,
|
|
const media_multistream_format& b)
|
|
{
|
|
if (a.avg_bit_rate != 0 && b.avg_bit_rate != 0
|
|
&& a.avg_bit_rate != b.avg_bit_rate) {
|
|
return false;
|
|
}
|
|
if (a.max_bit_rate != 0 && b.max_bit_rate != 0
|
|
&& a.max_bit_rate != b.max_bit_rate) {
|
|
return false;
|
|
}
|
|
if (a.avg_chunk_size != 0 && b.avg_chunk_size != 0
|
|
&& a.avg_chunk_size != b.avg_chunk_size) {
|
|
return false;
|
|
}
|
|
if (a.max_chunk_size != 0 && b.max_chunk_size != 0
|
|
&& a.max_chunk_size != b.max_chunk_size) {
|
|
return false;
|
|
}
|
|
if (a.flags != 0 && b.flags != 0 && a.flags != b.flags)
|
|
return false;
|
|
if (a.format != 0 && b.format != 0 && a.format != b.format)
|
|
return false;
|
|
|
|
if (a.format == 0 && b.format == 0) {
|
|
// TODO: How do we compare two formats with no type?
|
|
return true;
|
|
}
|
|
|
|
switch ((a.format != 0) ? a.format : b.format) {
|
|
default:
|
|
return true; // TODO: really?
|
|
|
|
case media_multistream_format::B_VID:
|
|
if (a.u.vid.frame_rate != 0 && b.u.vid.frame_rate != 0
|
|
&& a.u.vid.frame_rate != b.u.vid.frame_rate) {
|
|
return false;
|
|
}
|
|
if (a.u.vid.width != 0 && b.u.vid.width != 0
|
|
&& a.u.vid.width != b.u.vid.width) {
|
|
return false;
|
|
}
|
|
if (a.u.vid.height != 0 && b.u.vid.height != 0
|
|
&& a.u.vid.height != b.u.vid.height) {
|
|
return false;
|
|
}
|
|
if (a.u.vid.space != 0 && b.u.vid.space != 0
|
|
&& a.u.vid.space != b.u.vid.space) {
|
|
return false;
|
|
}
|
|
if (a.u.vid.sampling_rate != 0 && b.u.vid.sampling_rate != 0
|
|
&& a.u.vid.sampling_rate != b.u.vid.sampling_rate) {
|
|
return false;
|
|
}
|
|
if (a.u.vid.sample_format != 0 && b.u.vid.sample_format != 0
|
|
&& a.u.vid.sample_format != b.u.vid.sample_format) {
|
|
return false;
|
|
}
|
|
if (a.u.vid.byte_order != 0 && b.u.vid.byte_order != 0
|
|
&& a.u.vid.byte_order != b.u.vid.byte_order) {
|
|
return false;
|
|
}
|
|
if (a.u.vid.channel_count != 0 && b.u.vid.channel_count != 0
|
|
&& a.u.vid.channel_count != b.u.vid.channel_count) {
|
|
return false;
|
|
}
|
|
return true;
|
|
|
|
case media_multistream_format::B_AVI:
|
|
if (a.u.avi.us_per_frame != 0 && b.u.avi.us_per_frame != 0
|
|
&& a.u.avi.us_per_frame != b.u.avi.us_per_frame) {
|
|
return false;
|
|
}
|
|
if (a.u.avi.width != 0 && b.u.avi.width != 0
|
|
&& a.u.avi.width != b.u.avi.width) {
|
|
return false;
|
|
}
|
|
if (a.u.avi.height != 0 && b.u.avi.height != 0
|
|
&& a.u.avi.height != b.u.avi.height) {
|
|
return false;
|
|
}
|
|
if (a.u.avi.type_count != 0 && b.u.avi.type_count != 0
|
|
&& a.u.avi.type_count != b.u.avi.type_count) {
|
|
return false;
|
|
}
|
|
if (a.u.avi.types[0] != 0 && b.u.avi.types[0] != 0
|
|
&& a.u.avi.types[0] != b.u.avi.types[0]) {
|
|
return false;
|
|
}
|
|
if (a.u.avi.types[1] != 0 && b.u.avi.types[1] != 0
|
|
&& a.u.avi.types[1] != b.u.avi.types[1]) {
|
|
return false;
|
|
}
|
|
if (a.u.avi.types[2] != 0 && b.u.avi.types[2] != 0
|
|
&& a.u.avi.types[2] != b.u.avi.types[2]) {
|
|
return false;
|
|
}
|
|
if (a.u.avi.types[3] != 0 && b.u.avi.types[3] != 0
|
|
&& a.u.avi.types[3] != b.u.avi.types[3]) {
|
|
return false;
|
|
}
|
|
if (a.u.avi.types[4] != 0 && b.u.avi.types[4] != 0
|
|
&& a.u.avi.types[4] != b.u.avi.types[4]) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
static bool
|
|
encoded_audio_format_matches(const media_encoded_audio_format& a,
|
|
const media_encoded_audio_format& b)
|
|
{
|
|
if (!raw_audio_format_matches(a.output, b.output))
|
|
return false;
|
|
if (a.encoding != 0 && b.encoding != 0 && a.encoding != b.encoding)
|
|
return false;
|
|
if (a.bit_rate != 0 && b.bit_rate != 0 && a.bit_rate != b.bit_rate)
|
|
return false;
|
|
if (a.frame_size != 0 && b.frame_size != 0 && a.frame_size != b.frame_size)
|
|
return false;
|
|
if (!multi_audio_info_matches(a.multi_info, b.multi_info))
|
|
return false;
|
|
|
|
if (a.encoding == 0 && b.encoding == 0)
|
|
return true; // can't compare
|
|
|
|
switch((a.encoding != 0) ? a.encoding : b.encoding) {
|
|
case media_encoded_audio_format::B_ANY:
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
static bool
|
|
encoded_video_format_matches(const media_encoded_video_format& a,
|
|
const media_encoded_video_format& b)
|
|
{
|
|
if (!raw_video_format_matches(a.output, b.output))
|
|
return false;
|
|
if (a.encoding != 0 && b.encoding != 0 && a.encoding != b.encoding)
|
|
return false;
|
|
|
|
if (a.avg_bit_rate != 0 && b.avg_bit_rate != 0
|
|
&& a.avg_bit_rate != b.avg_bit_rate) {
|
|
return false;
|
|
}
|
|
if (a.max_bit_rate != 0 && b.max_bit_rate != 0
|
|
&& a.max_bit_rate != b.max_bit_rate) {
|
|
return false;
|
|
}
|
|
if (a.frame_size != 0 && b.frame_size != 0
|
|
&& a.frame_size != b.frame_size) {
|
|
return false;
|
|
}
|
|
if (a.forward_history != 0 && b.forward_history != 0
|
|
&& a.forward_history != b.forward_history) {
|
|
return false;
|
|
}
|
|
if (a.backward_history != 0 && b.backward_history != 0
|
|
&& a.backward_history != b.backward_history) {
|
|
return false;
|
|
}
|
|
|
|
if (a.encoding == 0 && b.encoding == 0)
|
|
return true; // can't compare
|
|
|
|
switch((a.encoding != 0) ? a.encoding : b.encoding) {
|
|
case media_encoded_video_format::B_ANY:
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
// #pragma mark - media_format::SpecializeTo() support
|
|
|
|
|
|
static void
|
|
raw_audio_format_specialize(media_raw_audio_format* format,
|
|
const media_raw_audio_format* other)
|
|
{
|
|
if (format->frame_rate == 0)
|
|
format->frame_rate = other->frame_rate;
|
|
if (format->channel_count == 0)
|
|
format->channel_count = other->channel_count;
|
|
if (format->format == 0)
|
|
format->format = other->format;
|
|
if (format->byte_order == 0)
|
|
format->byte_order = other->byte_order;
|
|
if (format->buffer_size == 0)
|
|
format->buffer_size = other->buffer_size;
|
|
if (format->frame_rate == 0)
|
|
format->frame_rate = other->frame_rate;
|
|
}
|
|
|
|
|
|
static void
|
|
multi_audio_info_specialize(media_multi_audio_info* format,
|
|
const media_multi_audio_info* other)
|
|
{
|
|
if (format->channel_mask == 0)
|
|
format->channel_mask = other->channel_mask;
|
|
if (format->valid_bits == 0)
|
|
format->valid_bits = other->valid_bits;
|
|
if (format->matrix_mask == 0)
|
|
format->matrix_mask = other->matrix_mask;
|
|
}
|
|
|
|
|
|
static void
|
|
multi_audio_format_specialize(media_multi_audio_format* format,
|
|
const media_multi_audio_format* other)
|
|
{
|
|
raw_audio_format_specialize(format, other);
|
|
multi_audio_info_specialize(format, other);
|
|
}
|
|
|
|
|
|
static void
|
|
raw_video_format_specialize(media_raw_video_format* format,
|
|
const media_raw_video_format* other)
|
|
{
|
|
if (format->field_rate == 0)
|
|
format->field_rate = other->field_rate;
|
|
if (format->interlace == 0)
|
|
format->interlace = other->interlace;
|
|
if (format->first_active == 0)
|
|
format->first_active = other->first_active;
|
|
if (format->last_active == 0)
|
|
format->last_active = other->last_active;
|
|
if (format->orientation == 0)
|
|
format->orientation = other->orientation;
|
|
if (format->pixel_width_aspect == 0)
|
|
format->pixel_width_aspect = other->pixel_width_aspect;
|
|
if (format->pixel_height_aspect == 0)
|
|
format->pixel_height_aspect = other->pixel_height_aspect;
|
|
if (format->display.format == 0)
|
|
format->display.format = other->display.format;
|
|
if (format->display.line_width == 0)
|
|
format->display.line_width = other->display.line_width;
|
|
if (format->display.line_count == 0)
|
|
format->display.line_count = other->display.line_count;
|
|
if (format->display.bytes_per_row == 0)
|
|
format->display.bytes_per_row = other->display.bytes_per_row;
|
|
if (format->display.pixel_offset == 0)
|
|
format->display.pixel_offset = other->display.pixel_offset;
|
|
if (format->display.line_offset == 0)
|
|
format->display.line_offset = other->display.line_offset;
|
|
if (format->display.flags == 0)
|
|
format->display.flags = other->display.flags;
|
|
}
|
|
|
|
|
|
static void
|
|
multistream_format_specialize(media_multistream_format* format,
|
|
const media_multistream_format* other)
|
|
{
|
|
if (format->avg_bit_rate == 0)
|
|
format->avg_bit_rate = other->avg_bit_rate;
|
|
if (format->max_bit_rate == 0)
|
|
format->max_bit_rate = other->max_bit_rate;
|
|
if (format->avg_chunk_size == 0)
|
|
format->avg_chunk_size = other->avg_chunk_size;
|
|
if (format->max_chunk_size == 0)
|
|
format->max_chunk_size = other->max_chunk_size;
|
|
if (format->flags == 0)
|
|
format->flags = other->flags;
|
|
if (format->format == 0)
|
|
format->format = other->format;
|
|
|
|
switch (format->format) {
|
|
case media_multistream_format::B_VID:
|
|
if (format->u.vid.frame_rate == 0)
|
|
format->u.vid.frame_rate = other->u.vid.frame_rate;
|
|
if (format->u.vid.width == 0)
|
|
format->u.vid.width = other->u.vid.width;
|
|
if (format->u.vid.height == 0)
|
|
format->u.vid.height = other->u.vid.height;
|
|
if (format->u.vid.space == 0)
|
|
format->u.vid.space = other->u.vid.space;
|
|
if (format->u.vid.sampling_rate == 0)
|
|
format->u.vid.sampling_rate = other->u.vid.sampling_rate;
|
|
if (format->u.vid.sample_format == 0)
|
|
format->u.vid.sample_format = other->u.vid.sample_format;
|
|
if (format->u.vid.byte_order == 0)
|
|
format->u.vid.byte_order = other->u.vid.byte_order;
|
|
if (format->u.vid.channel_count == 0)
|
|
format->u.vid.channel_count = other->u.vid.channel_count;
|
|
break;
|
|
|
|
case media_multistream_format::B_AVI:
|
|
if (format->u.avi.us_per_frame == 0)
|
|
format->u.avi.us_per_frame = other->u.avi.us_per_frame;
|
|
if (format->u.avi.width == 0)
|
|
format->u.avi.width = other->u.avi.width;
|
|
if (format->u.avi.height == 0)
|
|
format->u.avi.height = other->u.avi.height;
|
|
if (format->u.avi.type_count == 0)
|
|
format->u.avi.type_count = other->u.avi.type_count;
|
|
if (format->u.avi.types[0] == 0)
|
|
format->u.avi.types[0] = other->u.avi.types[0];
|
|
if (format->u.avi.types[1] == 0)
|
|
format->u.avi.types[1] = other->u.avi.types[1];
|
|
if (format->u.avi.types[2] == 0)
|
|
format->u.avi.types[2] = other->u.avi.types[2];
|
|
if (format->u.avi.types[3] == 0)
|
|
format->u.avi.types[3] = other->u.avi.types[3];
|
|
if (format->u.avi.types[4] == 0)
|
|
format->u.avi.types[4] = other->u.avi.types[4];
|
|
break;
|
|
|
|
default:
|
|
ERROR("media_format::SpecializeTo can't specialize "
|
|
"media_multistream_format of format %" B_PRId32 "\n",
|
|
format->format);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
encoded_audio_format_specialize(media_encoded_audio_format* format,
|
|
const media_encoded_audio_format* other)
|
|
{
|
|
raw_audio_format_specialize(&format->output, &other->output);
|
|
if (format->encoding == 0)
|
|
format->encoding = other->encoding;
|
|
if (format->bit_rate == 0)
|
|
format->bit_rate = other->bit_rate;
|
|
if (format->frame_size == 0)
|
|
format->frame_size = other->frame_size;
|
|
multi_audio_info_specialize(&format->multi_info, &other->multi_info);
|
|
}
|
|
|
|
|
|
static void
|
|
encoded_video_format_specialize(media_encoded_video_format* format,
|
|
const media_encoded_video_format* other)
|
|
{
|
|
raw_video_format_specialize(&format->output, &other->output);
|
|
if (format->avg_bit_rate == 0)
|
|
format->avg_bit_rate = other->avg_bit_rate;
|
|
if (format->max_bit_rate == 0)
|
|
format->max_bit_rate = other->max_bit_rate;
|
|
if (format->encoding == 0)
|
|
format->encoding = other->encoding;
|
|
if (format->frame_size == 0)
|
|
format->frame_size = other->frame_size;
|
|
if (format->forward_history == 0)
|
|
format->forward_history = other->forward_history;
|
|
if (format->backward_history == 0)
|
|
format->backward_history = other->backward_history;
|
|
}
|
|
|
|
|
|
// #pragma mark - media_format
|
|
|
|
|
|
bool
|
|
media_format::Matches(const media_format* other) const
|
|
{
|
|
CALLED();
|
|
|
|
if (type == 0 && other->type == 0) {
|
|
// TODO: How do we compare two formats with no type?
|
|
return true;
|
|
}
|
|
|
|
if (type != 0 && other->type != 0 && type != other->type)
|
|
return false;
|
|
|
|
switch ((type != 0) ? type : other->type) {
|
|
case B_MEDIA_RAW_AUDIO:
|
|
return multi_audio_format_matches(u.raw_audio, other->u.raw_audio);
|
|
|
|
case B_MEDIA_RAW_VIDEO:
|
|
return raw_video_format_matches(u.raw_video, other->u.raw_video);
|
|
|
|
case B_MEDIA_MULTISTREAM:
|
|
return multistream_format_matches(u.multistream,
|
|
other->u.multistream);
|
|
|
|
case B_MEDIA_ENCODED_AUDIO:
|
|
return encoded_audio_format_matches(u.encoded_audio,
|
|
other->u.encoded_audio);
|
|
|
|
case B_MEDIA_ENCODED_VIDEO:
|
|
return encoded_video_format_matches(u.encoded_video,
|
|
other->u.encoded_video);
|
|
|
|
default:
|
|
return true; // TODO: really?
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
media_format::SpecializeTo(const media_format* otherFormat)
|
|
{
|
|
CALLED();
|
|
|
|
if (type == 0 && otherFormat->type == 0) {
|
|
ERROR("media_format::SpecializeTo can't specialize wildcard to other "
|
|
"wildcard format\n");
|
|
return;
|
|
}
|
|
|
|
if (type == 0)
|
|
type = otherFormat->type;
|
|
|
|
switch (type) {
|
|
case B_MEDIA_RAW_AUDIO:
|
|
multi_audio_format_specialize(&u.raw_audio,
|
|
&otherFormat->u.raw_audio);
|
|
return;
|
|
|
|
case B_MEDIA_RAW_VIDEO:
|
|
raw_video_format_specialize(&u.raw_video,
|
|
&otherFormat->u.raw_video);
|
|
return;
|
|
|
|
case B_MEDIA_MULTISTREAM:
|
|
multistream_format_specialize(&u.multistream,
|
|
&otherFormat->u.multistream);
|
|
return;
|
|
|
|
case B_MEDIA_ENCODED_AUDIO:
|
|
encoded_audio_format_specialize(&u.encoded_audio,
|
|
&otherFormat->u.encoded_audio);
|
|
return;
|
|
|
|
case B_MEDIA_ENCODED_VIDEO:
|
|
encoded_video_format_specialize(&u.encoded_video,
|
|
&otherFormat->u.encoded_video);
|
|
return;
|
|
|
|
default:
|
|
ERROR("media_format::SpecializeTo can't specialize format "
|
|
"type %d\n", type);
|
|
}
|
|
}
|
|
|
|
|
|
status_t
|
|
media_format::SetMetaData(const void* data, size_t size)
|
|
{
|
|
if (!data || size > META_DATA_MAX_SIZE)
|
|
return B_BAD_VALUE;
|
|
|
|
void* new_addr;
|
|
area_id new_area;
|
|
if (size < META_DATA_AREA_MIN_SIZE) {
|
|
new_area = B_BAD_VALUE;
|
|
new_addr = malloc(size);
|
|
if (!new_addr)
|
|
return B_NO_MEMORY;
|
|
} else {
|
|
new_area = create_area("meta_data_area", &new_addr, B_ANY_ADDRESS,
|
|
ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
|
if (new_area < 0)
|
|
return (status_t)new_area;
|
|
}
|
|
|
|
if (meta_data_area > 0)
|
|
delete_area(meta_data_area);
|
|
else
|
|
free(meta_data);
|
|
|
|
meta_data = new_addr;
|
|
meta_data_size = size;
|
|
meta_data_area = new_area;
|
|
|
|
memcpy(meta_data, data, size);
|
|
|
|
if (meta_data_area > 0)
|
|
set_area_protection(meta_data_area, B_READ_AREA);
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
const void*
|
|
media_format::MetaData() const
|
|
{
|
|
return meta_data;
|
|
}
|
|
|
|
|
|
int32
|
|
media_format::MetaDataSize() const
|
|
{
|
|
return meta_data_size;
|
|
}
|
|
|
|
|
|
void
|
|
media_format::Unflatten(const char *flatBuffer)
|
|
{
|
|
// TODO: we should not!!! make flat copies of media_format
|
|
memcpy(this, flatBuffer, sizeof(*this));
|
|
meta_data = NULL;
|
|
meta_data_area = B_BAD_VALUE;
|
|
}
|
|
|
|
|
|
void
|
|
media_format::Clear()
|
|
{
|
|
memset(this, 0x00, sizeof(*this));
|
|
meta_data = NULL;
|
|
meta_data_area = B_BAD_VALUE;
|
|
}
|
|
|
|
|
|
media_format::media_format()
|
|
{
|
|
this->Clear();
|
|
}
|
|
|
|
|
|
media_format::media_format(const media_format& other)
|
|
{
|
|
this->Clear();
|
|
*this = other;
|
|
}
|
|
|
|
|
|
media_format::~media_format()
|
|
{
|
|
if (meta_data_area > 0)
|
|
delete_area(meta_data_area);
|
|
else
|
|
free(meta_data);
|
|
}
|
|
|
|
|
|
// final
|
|
media_format&
|
|
media_format::operator=(const media_format& clone)
|
|
{
|
|
// get rid of this format's meta data
|
|
this->~media_format();
|
|
// danger: using only ~media_format() would call the constructor
|
|
|
|
// make a binary copy
|
|
memcpy(this, &clone, sizeof(*this));
|
|
// some binary copies are invalid:
|
|
meta_data = NULL;
|
|
meta_data_area = B_BAD_VALUE;
|
|
|
|
// clone or copy the meta data
|
|
if (clone.meta_data) {
|
|
if (clone.meta_data_area != B_BAD_VALUE) {
|
|
meta_data_area = clone_area("meta_data_clone_area", &meta_data,
|
|
B_ANY_ADDRESS, B_READ_AREA, clone.meta_data_area);
|
|
if (meta_data_area < 0) {
|
|
// whoops, we just lost our meta data
|
|
meta_data = NULL;
|
|
meta_data_size = 0;
|
|
}
|
|
} else {
|
|
meta_data = malloc(meta_data_size);
|
|
if (meta_data) {
|
|
memcpy(meta_data, clone.meta_data, meta_data_size);
|
|
} else {
|
|
// whoops, we just lost our meta data
|
|
meta_data_size = 0;
|
|
}
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
bool
|
|
operator==(const media_raw_audio_format& a, const media_raw_audio_format& b)
|
|
{
|
|
return a.frame_rate == b.frame_rate
|
|
&& a.channel_count == b.channel_count
|
|
&& a.format == b.format
|
|
&& a.byte_order == b.byte_order
|
|
&& a.buffer_size == b.buffer_size;
|
|
}
|
|
|
|
|
|
bool
|
|
operator==(const media_multi_audio_info& a, const media_multi_audio_info& b)
|
|
{
|
|
return a.channel_mask == b.channel_mask
|
|
&& a.valid_bits == b.valid_bits
|
|
&& a.matrix_mask == b.matrix_mask;
|
|
}
|
|
|
|
|
|
bool
|
|
operator==(const media_multi_audio_format& a,
|
|
const media_multi_audio_format& b)
|
|
{
|
|
return (media_raw_audio_format)a == (media_raw_audio_format)b
|
|
&& (media_multi_audio_info)a == (media_multi_audio_info)b;
|
|
}
|
|
|
|
|
|
bool
|
|
operator==(const media_encoded_audio_format& a,
|
|
const media_encoded_audio_format& b)
|
|
{
|
|
return a.output == b.output
|
|
&& a.encoding == b.encoding
|
|
&& a.bit_rate == b.bit_rate
|
|
&& a.frame_size == b.frame_size
|
|
&& a.multi_info == b.multi_info;
|
|
}
|
|
|
|
|
|
bool
|
|
operator==(const media_video_display_info& a,
|
|
const media_video_display_info& b)
|
|
{
|
|
return a.format == b.format
|
|
&& a.line_width == b.line_width
|
|
&& a.line_count == b.line_count
|
|
&& a.bytes_per_row == b.bytes_per_row
|
|
&& a.pixel_offset == b.pixel_offset
|
|
&& a.line_offset == b.line_offset
|
|
&& a.flags == b.flags;
|
|
}
|
|
|
|
|
|
bool
|
|
operator==(const media_raw_video_format& a, const media_raw_video_format& b)
|
|
{
|
|
return a.field_rate == b.field_rate
|
|
&& a.interlace == b.interlace
|
|
&& a.first_active == b.first_active
|
|
&& a.last_active == b.last_active
|
|
&& a.orientation == b.orientation
|
|
&& a.pixel_width_aspect == b.pixel_width_aspect
|
|
&& a.pixel_height_aspect == b.pixel_height_aspect
|
|
&& a.display == b.display;
|
|
}
|
|
|
|
|
|
bool
|
|
operator==(const media_encoded_video_format& a,
|
|
const media_encoded_video_format& b)
|
|
{
|
|
return a.output == b.output
|
|
&& a.avg_bit_rate == b.avg_bit_rate
|
|
&& a.max_bit_rate == b.max_bit_rate
|
|
&& a.encoding == b.encoding
|
|
&& a.frame_size == b.frame_size
|
|
&& a.forward_history == b.forward_history
|
|
&& a.backward_history == b.backward_history;
|
|
}
|
|
|
|
|
|
bool
|
|
operator==(const media_multistream_format::vid_info& a,
|
|
const media_multistream_format::vid_info& b)
|
|
{
|
|
return a.frame_rate == b.frame_rate
|
|
&& a.width == b.width
|
|
&& a.height == b.height
|
|
&& a.space == b.space
|
|
&& a.sampling_rate == b.sampling_rate
|
|
&& a.sample_format == b.sample_format
|
|
&& a.byte_order == b.byte_order
|
|
&& a.channel_count == b.channel_count;
|
|
}
|
|
|
|
|
|
bool
|
|
operator==(const media_multistream_format::avi_info& a,
|
|
const media_multistream_format::avi_info& b)
|
|
{
|
|
return a.us_per_frame == b.us_per_frame
|
|
&& a.width == b.width
|
|
&& a.height == b.height
|
|
&& a.type_count == b.type_count
|
|
&& a.types[0] == b.types[0]
|
|
&& a.types[1] == b.types[1]
|
|
&& a.types[2] == b.types[2]
|
|
&& a.types[3] == b.types[3]
|
|
&& a.types[4] == b.types[4];
|
|
}
|
|
|
|
|
|
bool
|
|
operator==(const media_multistream_format& a,
|
|
const media_multistream_format& b)
|
|
{
|
|
if (a.avg_bit_rate != b.avg_bit_rate
|
|
|| a.max_bit_rate != b.max_bit_rate
|
|
|| a.avg_chunk_size != b.avg_chunk_size
|
|
|| a.max_chunk_size != b.max_chunk_size
|
|
|| a.format != b.format
|
|
|| a.flags != b.flags) {
|
|
return false;
|
|
}
|
|
|
|
switch (a.format) {
|
|
case media_multistream_format::B_VID:
|
|
return a.u.vid == b.u.vid;
|
|
|
|
case media_multistream_format::B_AVI:
|
|
return a.u.avi == b.u.avi;
|
|
|
|
default:
|
|
return true; // TODO: really?
|
|
}
|
|
}
|
|
|
|
|
|
bool
|
|
operator==(const media_format& a, const media_format& b)
|
|
{
|
|
if (a.type != b.type
|
|
|| a.user_data_type != b.user_data_type
|
|
// TODO: compare user_data[48] ?
|
|
|| a.require_flags != b.require_flags
|
|
|| a.deny_flags != b.deny_flags) {
|
|
return false;
|
|
}
|
|
|
|
switch (a.type) {
|
|
case B_MEDIA_RAW_AUDIO:
|
|
return a.u.raw_audio == b.u.raw_audio;
|
|
|
|
case B_MEDIA_RAW_VIDEO:
|
|
return a.u.raw_video == b.u.raw_video;
|
|
|
|
case B_MEDIA_MULTISTREAM:
|
|
return a.u.multistream == b.u.multistream;
|
|
|
|
case B_MEDIA_ENCODED_AUDIO:
|
|
return a.u.encoded_audio == b.u.encoded_audio;
|
|
|
|
case B_MEDIA_ENCODED_VIDEO:
|
|
return a.u.encoded_video == b.u.encoded_video;
|
|
|
|
default:
|
|
return true; // TODO: really?
|
|
}
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
/*! return \c true if a and b are compatible (accounting for wildcards)
|
|
a is the format you want to feed to something accepting b
|
|
*/
|
|
bool
|
|
format_is_compatible(const media_format& a, const media_format& b)
|
|
{
|
|
return a.Matches(&b);
|
|
}
|
|
|
|
|
|
bool
|
|
string_for_format(const media_format& f, char* buf, size_t size)
|
|
{
|
|
char encoding[10]; /* maybe Be wanted to use some 4CCs ? */
|
|
const char* videoOrientation = "0"; /* I'd use "NC", R5 uses 0. */
|
|
|
|
if (buf == NULL)
|
|
return false;
|
|
switch (f.type) {
|
|
case B_MEDIA_RAW_AUDIO:
|
|
snprintf(buf, size,
|
|
"raw_audio;%g;%" B_PRIu32 ";0x%" B_PRIx32 ";%" B_PRIu32 ";0x%"
|
|
B_PRIxSIZE ";0x%#" B_PRIx32 ";%d;0x%04x",
|
|
f.u.raw_audio.frame_rate,
|
|
f.u.raw_audio.channel_count,
|
|
f.u.raw_audio.format,
|
|
f.u.raw_audio.byte_order,
|
|
f.u.raw_audio.buffer_size,
|
|
f.u.raw_audio.channel_mask,
|
|
f.u.raw_audio.valid_bits,
|
|
f.u.raw_audio.matrix_mask);
|
|
return true;
|
|
case B_MEDIA_RAW_VIDEO:
|
|
if (f.u.raw_video.orientation == B_VIDEO_TOP_LEFT_RIGHT)
|
|
videoOrientation = "TopLR";
|
|
else if (f.u.raw_video.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT)
|
|
videoOrientation = "BotLR";
|
|
snprintf(buf, size, "raw_video;%g;0x%x;%" B_PRIu32 ";%" B_PRIu32 ";%"
|
|
B_PRIu32 ";%" B_PRIu32 ";%s;%d;%d",
|
|
f.u.raw_video.field_rate,
|
|
f.u.raw_video.display.format,
|
|
f.u.raw_video.interlace,
|
|
f.u.raw_video.display.line_width,
|
|
f.u.raw_video.display.line_count,
|
|
f.u.raw_video.first_active,
|
|
videoOrientation,
|
|
f.u.raw_video.pixel_width_aspect,
|
|
f.u.raw_video.pixel_height_aspect);
|
|
return true;
|
|
case B_MEDIA_ENCODED_AUDIO:
|
|
snprintf(encoding, 10, "%d", f.u.encoded_audio.encoding);
|
|
snprintf(buf, size,
|
|
"caudio;%s;%g;%ld;(%g;%" B_PRIu32 ";0x%" B_PRIx32 ";%" B_PRIu32
|
|
";0x%" B_PRIxSIZE ";0x%08" B_PRIx32 ";%d;0x%04x)",
|
|
encoding,
|
|
f.u.encoded_audio.bit_rate,
|
|
f.u.encoded_audio.frame_size,
|
|
f.u.encoded_audio.output.frame_rate,
|
|
f.u.encoded_audio.output.channel_count,
|
|
f.u.encoded_audio.output.format,
|
|
f.u.encoded_audio.output.byte_order,
|
|
f.u.encoded_audio.output.buffer_size,
|
|
f.u.encoded_audio.multi_info.channel_mask,
|
|
f.u.encoded_audio.multi_info.valid_bits,
|
|
f.u.encoded_audio.multi_info.matrix_mask);
|
|
return true;
|
|
case B_MEDIA_ENCODED_VIDEO:
|
|
snprintf(encoding, 10, "%d", f.u.encoded_video.encoding);
|
|
if (f.u.encoded_video.output.orientation == B_VIDEO_TOP_LEFT_RIGHT)
|
|
videoOrientation = "TopLR";
|
|
else if (f.u.encoded_video.output.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT)
|
|
videoOrientation = "BotLR";
|
|
snprintf(buf, size,
|
|
"cvideo;%s;%g;%g;%" B_PRIuSIZE ";(%g;0x%x;%" B_PRIu32 ";%" B_PRIu32
|
|
";%" B_PRIu32 ";%" B_PRIu32 ";%s;%d;%d)",
|
|
encoding,
|
|
f.u.encoded_video.avg_bit_rate,
|
|
f.u.encoded_video.max_bit_rate,
|
|
f.u.encoded_video.frame_size,
|
|
f.u.encoded_video.output.field_rate,
|
|
f.u.encoded_video.output.display.format,
|
|
f.u.encoded_video.output.interlace,
|
|
f.u.encoded_video.output.display.line_width,
|
|
f.u.encoded_video.output.display.line_count,
|
|
f.u.encoded_video.output.first_active,
|
|
videoOrientation,
|
|
f.u.encoded_video.output.pixel_width_aspect,
|
|
f.u.encoded_video.output.pixel_height_aspect);
|
|
return true;
|
|
default:
|
|
snprintf(buf, size, "%d-", f.type);
|
|
unsigned char* p = (unsigned char*)&(f.u);
|
|
size -= strlen(buf);
|
|
buf += strlen(buf);
|
|
for (int i = 0; (size > 2) && (i < 96); i++) {
|
|
snprintf(buf, 3, "%2.2x", *(p + i));
|
|
buf+=2;
|
|
size-=2;
|
|
}
|
|
return true; // ?
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
bool
|
|
operator==(const media_file_format_id& a, const media_file_format_id& b)
|
|
{
|
|
return a.node == b.node && a.device == b.device
|
|
&& a.internal_id == b.internal_id;
|
|
}
|
|
|
|
|
|
bool
|
|
operator<(const media_file_format_id& a, const media_file_format_id& b)
|
|
{
|
|
return a.internal_id < b.internal_id;
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
//! Use this function to iterate through available file format writers.
|
|
status_t
|
|
get_next_file_format(int32* cookie, media_file_format* mff)
|
|
{
|
|
if (cookie == NULL || mff == NULL)
|
|
return B_BAD_VALUE;
|
|
|
|
status_t ret = AddOnManager::GetInstance()->GetFileFormat(mff, *cookie);
|
|
if (ret != B_OK)
|
|
return ret;
|
|
|
|
*cookie = *cookie + 1;
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
// final & verified
|
|
const char* B_MEDIA_SERVER_SIGNATURE = "application/x-vnd.Be.media-server";
|
|
const char* B_MEDIA_ADDON_SERVER_SIGNATURE = "application/x-vnd.Be.addon-host";
|
|
|
|
const type_code B_CODEC_TYPE_INFO = 0x040807b2;
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
// shutdown_media_server() and launch_media_server()
|
|
// are provided by libbe.so in BeOS R5
|
|
|
|
#define MEDIA_SERVICE_NOTIFICATION_ID "MediaServiceNotificationID"
|
|
|
|
|
|
void
|
|
notify_system(float progress, const char* message)
|
|
{
|
|
BNotification notification(B_PROGRESS_NOTIFICATION);
|
|
notification.SetMessageID(MEDIA_SERVICE_NOTIFICATION_ID);
|
|
notification.SetProgress(progress);
|
|
notification.SetGroup(B_TRANSLATE("Media Service"));
|
|
notification.SetContent(message);
|
|
|
|
app_info info;
|
|
be_app->GetAppInfo(&info);
|
|
BBitmap icon(BRect(0, 0, 32, 32), B_RGBA32);
|
|
BNode node(&info.ref);
|
|
BIconUtils::GetVectorIcon(&node, "BEOS:ICON", &icon);
|
|
notification.SetIcon(&icon);
|
|
|
|
notification.Send();
|
|
}
|
|
|
|
|
|
void
|
|
progress_shutdown(int stage,
|
|
bool (*progress)(int stage, const char* message, void* cookie),
|
|
void* cookie)
|
|
{
|
|
// parameter "message" is no longer used. It is kept for compatibility with
|
|
// BeOS as this is used as a shutdown_media_server callback.
|
|
|
|
TRACE("stage: %i\n", stage);
|
|
const char* string = "Unknown stage";
|
|
switch (stage) {
|
|
case 10:
|
|
string = B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS);
|
|
break;
|
|
case 20:
|
|
string = B_TRANSLATE("Waiting for media_server to quit.");
|
|
break;
|
|
case 40:
|
|
string = B_TRANSLATE("Telling media_addon_server to quit.");
|
|
break;
|
|
case 50:
|
|
string = B_TRANSLATE("Waiting for media_addon_server to quit.");
|
|
break;
|
|
case 70:
|
|
string = B_TRANSLATE("Cleaning up.");
|
|
break;
|
|
case 100:
|
|
string = B_TRANSLATE("Done shutting down.");
|
|
break;
|
|
}
|
|
|
|
if (progress == NULL)
|
|
notify_system(stage / 100.0f, string);
|
|
else
|
|
progress(stage, string, cookie);
|
|
}
|
|
|
|
|
|
status_t
|
|
shutdown_media_server(bigtime_t timeout,
|
|
bool (*progress)(int stage, const char* message, void* cookie),
|
|
void* cookie)
|
|
{
|
|
BLaunchRoster launchRoster;
|
|
launchRoster.StopTarget(B_MEDIA_SERVER_SIGNATURE);
|
|
|
|
BMessage msg(B_QUIT_REQUESTED);
|
|
status_t err = B_MEDIA_SYSTEM_FAILURE;
|
|
bool shutdown = false;
|
|
|
|
BMediaRoster* roster = BMediaRoster::Roster(&err);
|
|
if (roster == NULL || err != B_OK)
|
|
return err;
|
|
|
|
if (progress == NULL && roster->Lock()) {
|
|
MediaRosterEx(roster)->EnableLaunchNotification(true, true);
|
|
roster->Unlock();
|
|
}
|
|
|
|
if ((err = msg.AddBool("be:_user_request", true)) != B_OK)
|
|
return err;
|
|
|
|
team_id mediaServer = be_roster->TeamFor(B_MEDIA_SERVER_SIGNATURE);
|
|
team_id addOnServer = be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE);
|
|
|
|
if (mediaServer != B_ERROR) {
|
|
BMessage reply;
|
|
BMessenger messenger(B_MEDIA_SERVER_SIGNATURE, mediaServer);
|
|
progress_shutdown(10, progress, cookie);
|
|
|
|
err = messenger.SendMessage(&msg, &reply, 2000000, 2000000);
|
|
reply.FindBool("_shutdown", &shutdown);
|
|
if (err == B_TIMED_OUT || shutdown == false) {
|
|
if (messenger.IsValid())
|
|
kill_team(mediaServer);
|
|
} else if (err != B_OK)
|
|
return err;
|
|
|
|
progress_shutdown(20, progress, cookie);
|
|
|
|
int32 rv;
|
|
if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK)
|
|
return rv;
|
|
}
|
|
|
|
if (addOnServer != B_ERROR) {
|
|
shutdown = false;
|
|
BMessage reply;
|
|
BMessenger messenger(B_MEDIA_ADDON_SERVER_SIGNATURE, addOnServer);
|
|
progress_shutdown(40, progress, cookie);
|
|
|
|
// The media_server usually shutdown the media_addon_server,
|
|
// if not let's do something.
|
|
if (messenger.IsValid()) {
|
|
err = messenger.SendMessage(&msg, &reply, 2000000, 2000000);
|
|
reply.FindBool("_shutdown", &shutdown);
|
|
if (err == B_TIMED_OUT || shutdown == false) {
|
|
if (messenger.IsValid())
|
|
kill_team(addOnServer);
|
|
} else if (err != B_OK)
|
|
return err;
|
|
|
|
progress_shutdown(50, progress, cookie);
|
|
|
|
int32 rv;
|
|
if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK)
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
progress_shutdown(100, progress, cookie);
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
void
|
|
progress_startup(int stage,
|
|
bool (*progress)(int stage, const char* message, void* cookie),
|
|
void* cookie)
|
|
{
|
|
// parameter "message" is no longer used. It is kept for compatibility with
|
|
// BeOS as this is used as a shutdown_media_server callback.
|
|
|
|
TRACE("stage: %i\n", stage);
|
|
const char* string = "Unknown stage";
|
|
switch (stage) {
|
|
case 10:
|
|
string = B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS);
|
|
break;
|
|
case 20:
|
|
string = B_TRANSLATE("Stopping media_addon_server.");
|
|
break;
|
|
case 50:
|
|
string = B_TRANSLATE("Starting media_services.");
|
|
break;
|
|
case 90:
|
|
string = B_TRANSLATE("Error occurred starting media services.");
|
|
break;
|
|
case 100:
|
|
string = B_TRANSLATE("Ready for use.");
|
|
break;
|
|
}
|
|
|
|
if (progress == NULL)
|
|
notify_system(stage / 100.0f, string);
|
|
else
|
|
progress(stage, string, cookie);
|
|
}
|
|
|
|
|
|
status_t
|
|
launch_media_server(bigtime_t timeout,
|
|
bool (*progress)(int stage, const char* message, void* cookie),
|
|
void* cookie, uint32 flags)
|
|
{
|
|
if (BMediaRoster::IsRunning())
|
|
return B_ALREADY_RUNNING;
|
|
|
|
status_t err = B_MEDIA_SYSTEM_FAILURE;
|
|
BMediaRoster* roster = BMediaRoster::Roster(&err);
|
|
if (roster == NULL || err != B_OK)
|
|
return err;
|
|
|
|
if (progress == NULL && roster->Lock()) {
|
|
MediaRosterEx(roster)->EnableLaunchNotification(true, true);
|
|
roster->Unlock();
|
|
}
|
|
|
|
// The media_server crashed
|
|
if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
|
|
progress_startup(10, progress, cookie);
|
|
kill_team(be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE));
|
|
}
|
|
|
|
// The media_addon_server crashed
|
|
if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
|
|
progress_startup(20, progress, cookie);
|
|
kill_team(be_roster->TeamFor(B_MEDIA_SERVER_SIGNATURE));
|
|
}
|
|
|
|
progress_startup(50, progress, cookie);
|
|
|
|
err = BLaunchRoster().Start(B_MEDIA_SERVER_SIGNATURE);
|
|
|
|
if (err != B_OK)
|
|
progress_startup(90, progress, cookie);
|
|
else if (progress != NULL) {
|
|
progress_startup(100, progress, cookie);
|
|
err = B_OK;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
// #pragma mark - media_encode_info
|
|
|
|
|
|
media_encode_info::media_encode_info()
|
|
{
|
|
flags = 0;
|
|
used_data_size = 0;
|
|
start_time = 0;
|
|
time_to_encode = INT64_MAX;
|
|
file_format_data = NULL;
|
|
file_format_data_size = 0;
|
|
codec_data = NULL;
|
|
codec_data_size = 0;
|
|
}
|
|
|
|
|
|
media_decode_info::media_decode_info()
|
|
{
|
|
time_to_decode = INT64_MAX;
|
|
file_format_data = NULL;
|
|
file_format_data_size = 0;
|
|
codec_data = NULL;
|
|
codec_data_size = 0;
|
|
}
|
|
|
|
|