root/src/apps/cortex/support/MediaString.cpp
/*
 * Copyright (c) 1999-2000, Eric Moon.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions, and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


// MediaString.cpp

#include "MediaString.h"

// Media Kit
#include <MediaFormats.h>
// Support Kit
#include <String.h>
#include <StringFormat.h>
// Locale Kit
#undef B_CATALOG
#define B_CATALOG (&sCatalog)
#include <Catalog.h>

#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "MediaString"

__USE_CORTEX_NAMESPACE

#include <Debug.h>
#define D_METHOD(x) //PRINT (x)

static BCatalog sCatalog("x-vnd.Cortex.support");

// -------------------------------------------------------- //
// *** media_node strings (public)
// -------------------------------------------------------- //

BString MediaString::getStringFor(
        node_kind kinds,
        bool complete) {
        D_METHOD(("MediaString::getStringFor(node_kind)\n"));

        BString list, last;
        bool first = true;

        if (kinds & B_BUFFER_PRODUCER) {
                if (first) {
                        list = B_TRANSLATE("Buffer producer");
                        first = false;
                }
        }
        if (kinds & B_BUFFER_CONSUMER) {
                if (first) {
                        list = B_TRANSLATE("Buffer consumer");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Buffer consumer");
                }
        }
        if (kinds & B_TIME_SOURCE) {
                if (first) {
                        list = B_TRANSLATE("Time source");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Time source");
                }
        }
        if (kinds & B_CONTROLLABLE) {
                if (first) {
                        list = B_TRANSLATE("Controllable");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Controllable");
                }
        }
        if (kinds & B_FILE_INTERFACE) {
                if (first) {
                        list = B_TRANSLATE("File interface");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("File interface");
                }
        }
        if (kinds & B_ENTITY_INTERFACE) {
                if (first) {
                        list = B_TRANSLATE("Entity interface");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Entity interface");
                }
        }
        if (kinds & B_PHYSICAL_INPUT) {
                if (first) {
                        list = B_TRANSLATE("Physical input");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Physical input");
                }
        }
        if (kinds & B_PHYSICAL_OUTPUT) {
                if (first) {
                        list = B_TRANSLATE("Physical output");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Physical output");
                }
        }
        if (kinds & B_SYSTEM_MIXER) {
                if (first) {
                        list = B_TRANSLATE("System mixer");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("System mixer");
                }
        }

        if (last != "")
                list << " & " << last;
        return list;
}

BString MediaString::getStringFor(
        BMediaNode::run_mode runMode,
        bool complete)
{
        D_METHOD(("MediaString::getStringFor(run_mode)\n"));

        switch (runMode) {
                case BMediaNode::B_OFFLINE:
                        return B_TRANSLATE("Offline");
                case BMediaNode::B_RECORDING:
                        return B_TRANSLATE("Recording");
                case BMediaNode::B_DECREASE_PRECISION:
                        return B_TRANSLATE("Decrease precision");
                case BMediaNode::B_INCREASE_LATENCY:
                        return B_TRANSLATE("Increase latency");
                case BMediaNode::B_DROP_DATA:
                        return B_TRANSLATE("Drop data");
                default:
                        return B_TRANSLATE("(unknown run mode)");
        }
}

// -------------------------------------------------------- //
// *** media_format strings (public)
// -------------------------------------------------------- //

BString MediaString::getStringFor(
        media_type type,
        bool complete) {
        D_METHOD(("MediaString::getStringFor(media_type)\n"));

        switch (type) {
                case B_MEDIA_NO_TYPE:
                        return B_TRANSLATE("Typeless media");
                case B_MEDIA_UNKNOWN_TYPE:
                        return B_TRANSLATE("Unknown media type");
                case B_MEDIA_RAW_AUDIO:
                        return B_TRANSLATE("Raw audio");
                case B_MEDIA_RAW_VIDEO:
                        return B_TRANSLATE("Raw video");
                case B_MEDIA_VBL:
                        return B_TRANSLATE("Raw data from VBL area");
                case B_MEDIA_TIMECODE:
                        return B_TRANSLATE("Timecode");
                case B_MEDIA_MIDI:
                        return B_TRANSLATE("MIDI");
                case B_MEDIA_TEXT:
                        return B_TRANSLATE("Text");
                case B_MEDIA_HTML:
                        return B_TRANSLATE("HTML");
                case B_MEDIA_MULTISTREAM:
                        return B_TRANSLATE("Multistream media");
                case B_MEDIA_PARAMETERS:
                        return B_TRANSLATE("Parameters");
                case B_MEDIA_ENCODED_AUDIO:
                        return B_TRANSLATE("Encoded audio");
                case B_MEDIA_ENCODED_VIDEO:
                        return B_TRANSLATE("Encoded video");
                default: {
                        if (type >= B_MEDIA_FIRST_USER_TYPE) {
                                return B_TRANSLATE("User-defined media type");
                        }
                        if (type >= B_MEDIA_PRIVATE) {
                                return B_TRANSLATE("Private Be media type");
                        }
                }
        }
        return B_TRANSLATE("Unknown media type");
}

BString MediaString::getStringFor(
        media_format_family family,
        bool complete) {
        D_METHOD(("MediaString::getStringFor(media_format_family)\n"));

        switch (family) {
                case B_ANY_FORMAT_FAMILY:
                        return B_TRANSLATE("Any format family");
                case B_BEOS_FORMAT_FAMILY:
                        return B_TRANSLATE("BeOS format family");
                case B_QUICKTIME_FORMAT_FAMILY:
                        return B_TRANSLATE("QuickTime format family");
                case B_AVI_FORMAT_FAMILY:
                        return B_TRANSLATE("AVI format family");
                case B_ASF_FORMAT_FAMILY:
                        return B_TRANSLATE("ASF format family");
                case B_MPEG_FORMAT_FAMILY:
                        return B_TRANSLATE("MPEG format family");
                case B_WAV_FORMAT_FAMILY:
                        return B_TRANSLATE("WAV format family");
                case B_AIFF_FORMAT_FAMILY:
                        return B_TRANSLATE("AIFF format family");
                default:
                        return B_TRANSLATE("Miscellaneous format family");
        }
}

BString MediaString::getStringFor(
        const media_multi_audio_format &format,
        bool complete) {
        D_METHOD(("MediaString::getStringFor(media_raw_audio_format)\n"));

        BString s = "";
        bool empty = true;

        // sample rate
        if (format.frame_rate != media_raw_audio_format::wildcard.frame_rate) {
                s << (empty ? "" : ", ") << forAudioFrameRate(format.frame_rate);
                empty = false;
        }

        // format
        if (format.format != media_raw_audio_format::wildcard.format) {
                s << (empty ? "" : ", ") << forAudioFormat(format.format, format.valid_bits);
                empty = false;
        }

        // channels
        if (format.channel_count != media_raw_audio_format::wildcard.channel_count) {
                s << (empty ? "" : ", ") << forAudioChannelCount(format.channel_count);
                empty = false;
        }

        if (complete) {
                // channel mask
                if (format.channel_mask != media_multi_audio_format::wildcard.channel_mask) {
                        s << (empty ? "" : " ") << "(" << forAudioChannelMask(format.channel_mask) << ")";
                        empty = false;
                }

                // matrix mask
                if (format.matrix_mask != media_multi_audio_format::wildcard.matrix_mask) {
                        s << (empty ? "" : " ") << "(" << forAudioMatrixMask(format.matrix_mask) << ")";
                        empty = false;
                }

                // endianess
                if (format.byte_order != media_raw_audio_format::wildcard.byte_order) {
                        s << (empty ? "" : ", ") << forAudioByteOrder(format.byte_order);
                        empty = false;
                }

                // buffer size
                if (format.buffer_size != media_raw_audio_format::wildcard.buffer_size) {
                        s << (empty ? "" : ", ") << forAudioBufferSize(format.buffer_size);
                        empty = false;
                }
        }

        return s;
}

BString MediaString::getStringFor(
        const media_raw_video_format &format,
        bool complete) {
        D_METHOD(("MediaString::getStringFor(media_raw_video_format)\n"));

        BString s = "";
        bool empty = true;

        // format / color space
        if (format.display.format != media_video_display_info::wildcard.format) {
                s << (empty ? "" : ", ") << forVideoFormat(format.display.format);
                empty = false;
        }

        // resolution
        if ((format.display.line_width != media_video_display_info::wildcard.line_width)
         && (format.display.line_count != media_video_display_info::wildcard.line_count)) {
                s << (empty ? "" : ", ") << forVideoResolution(format.display.line_width,
                                                                                                           format.display.line_count);
        }

        // field rate / interlace
        if (format.field_rate != media_raw_video_format::wildcard.field_rate) {
                s << (empty ? "" : ", ") << forVideoFieldRate(format.field_rate,
                                                                                                          format.interlace);
                empty = false;
        }

        if (complete) {

                // aspect ratio
                if ((format.pixel_width_aspect != media_raw_video_format::wildcard.pixel_width_aspect)
                 && (format.pixel_height_aspect != media_raw_video_format::wildcard.pixel_height_aspect)) {
                        s << (empty ? "" : ", ") << forVideoAspectRatio(format.pixel_width_aspect,
                                                                                                                        format.pixel_height_aspect);
                        empty = false;
                }

                // orientation
                if (format.orientation != media_raw_video_format::wildcard.orientation) {
                        s << (empty ? "" : ", ") << forVideoOrientation(format.orientation);
                        empty = false;
                }

                // active lines
                if ((format.first_active != media_raw_video_format::wildcard.first_active)
                 && (format.last_active != media_raw_video_format::wildcard.last_active)) {
                        s << (empty ? "" : ", ") << forVideoActiveLines(format.first_active,
                                                                                                                        format.last_active);
                        empty = false;
                }
        }
        return s;
}

BString MediaString::getStringFor(
        const media_encoded_audio_format &format,
        bool complete) {
        D_METHOD(("MediaString::getStringFor(media_encoded_audio_format)\n"));

        BString s = "";
        bool empty = true;

        // bit rate
        if (format.bit_rate != media_encoded_audio_format::wildcard.bit_rate) {
                s << (empty ? "" : ", ") << forAudioBitRate(format.bit_rate);
                empty = false;
        }

        // frame size
        if (format.frame_size != media_encoded_audio_format::wildcard.frame_size) {
                s << (empty ? "" : ", ") << forAudioFrameSize(format.frame_size);
                empty = false;
        }
        return s;
}

BString MediaString::getStringFor(
        const media_encoded_video_format &format,
        bool complete) {
        D_METHOD(("MediaString::getStringFor(media_encoded_video_format)\n"));

        BString s = "";
        bool empty = true;

        // bit rate
        if ((format.avg_bit_rate != media_encoded_video_format::wildcard.avg_bit_rate)
         && (format.max_bit_rate != media_encoded_video_format::wildcard.max_bit_rate)) {
                s << (empty ? "" : ", ") << forVideoBitRate(format.avg_bit_rate,
                                                                                                        format.max_bit_rate);
                empty = false;
        }

        if (complete) {

                // frame size
                if (format.frame_size != media_encoded_video_format::wildcard.frame_size) {
                        s << (empty ? "" : ", ") << forVideoFrameSize(format.frame_size);
                        empty = false;
                }

                // history
                if ((format.forward_history != media_encoded_video_format::wildcard.forward_history)
                 && (format.backward_history != media_encoded_video_format::wildcard.backward_history)) {
                        s << (empty ? "" : ", ") << forVideoHistory(format.forward_history,
                                                                                                                format.backward_history);
                        empty = false;
                }
        }

        return s;
}

BString MediaString::getStringFor(
        const media_multistream_format &format,
        bool complete) {
        D_METHOD(("MediaString::getStringFor(media_multistream_format)\n"));

        BString s = "";
        bool empty = true;
        
        // format
        if (format.format != media_multistream_format::wildcard.format) {
                s << (empty ? "" : ", ") << forMultistreamFormat(format.format);
                empty = false;
        }

        // bit rate
        if ((format.avg_bit_rate != media_multistream_format::wildcard.avg_bit_rate)
         && (format.max_bit_rate != media_multistream_format::wildcard.max_bit_rate)) {
                s << (empty ? "" : ", ") << forMultistreamBitRate(format.avg_bit_rate,
                                                                                                                  format.max_bit_rate);
                empty = false;
        }

        if (complete) {

                // chunk size
                if ((format.avg_chunk_size != media_multistream_format::wildcard.avg_chunk_size)
                 && (format.max_chunk_size != media_multistream_format::wildcard.max_chunk_size)) {
                        s << (empty ? "" : ", ") << forMultistreamChunkSize(format.avg_chunk_size,
                                                                                                                                format.max_chunk_size);
                        empty = false;
                }

                // flags
                if (format.flags != media_multistream_format::wildcard.flags) {
                        s << (empty ? "" : ", ") << forMultistreamFlags(format.flags);
                        empty = false;
                }
        }

        return s;
}

BString MediaString::getStringFor(
        const media_format &format,
        bool complete) {
        D_METHOD(("MediaString::getStringFor(media_format)\n"));

        BString s = getStringFor(format.type, complete);
        switch (format.type) {
                case B_MEDIA_RAW_AUDIO: {
                        BString formatInfo = getStringFor(format.u.raw_audio, complete);
                        if (formatInfo.Length() > 0)
                                s << " (" << formatInfo << ")";
                        break;
                }
                case B_MEDIA_RAW_VIDEO: {
                        BString formatInfo = getStringFor(format.u.raw_video, complete);
                        if (formatInfo.Length() > 0)
                                s << " (" << formatInfo << ")";
                        break;
                }
                case B_MEDIA_ENCODED_AUDIO:     {
                        BString formatInfo = getStringFor(format.u.encoded_audio, complete);
                        if (formatInfo.Length() > 0)
                                s << " (" << formatInfo << ")";
                        break;
                }
                case B_MEDIA_ENCODED_VIDEO: {
                        BString formatInfo = getStringFor(format.u.encoded_video, complete);
                        if (formatInfo.Length() > 0)
                                s << " (" << formatInfo << ")";
                        break;
                }
                case B_MEDIA_MULTISTREAM: {
                        BString formatInfo = getStringFor(format.u.multistream, complete);
                        if (formatInfo.Length() > 0)
                                s << " (" << formatInfo << ")";
                        break;
                }
                default: {
                        break;
                }
        }
        return s;
}

// -------------------------------------------------------- //
// *** media_source / media_destination strings (public)
// -------------------------------------------------------- //

BString MediaString::getStringFor(
        const media_source &source,
        bool complete) {
        D_METHOD(("MediaString::getStringFor(media_source)\n"));

        BString s;
        if ((source.port != media_source::null.port)
         && (source.id != media_source::null.id)) {
                s << B_TRANSLATE("Port") << " "
                        << source.port << ", "
                        << B_TRANSLATE("ID") << " "
                        << source.id;
        }
        else {
                s = B_TRANSLATE("(none)");
        }
        return s;
}

BString MediaString::getStringFor(
        const media_destination &destination,
        bool complete) {
        D_METHOD(("MediaString::getStringFor(media_destination)\n"));

        BString s;
        if ((destination.port != media_destination::null.port)
         && (destination.id != media_destination::null.id)) {
                s << B_TRANSLATE("Port") << " "
                        << destination.port << ", "
                        << B_TRANSLATE("ID") << " "
                        << destination.id;
        }
        else {
                s = B_TRANSLATE("(none)");
        }
        return s;
}

// -------------------------------------------------------- //
// *** strings for single fields in media_raw_audio_format 
//         (public)
// -------------------------------------------------------- //

BString MediaString::forAudioFormat(
        uint32 format,
        int32 validBits) {
        D_METHOD(("MediaString::forAudioFormat()\n"));

        if (format == media_raw_audio_format::wildcard.format) {
                return "*";
        }

        switch (format) {
                case media_raw_audio_format::B_AUDIO_UCHAR: {
                        return B_TRANSLATE("8 bit integer");
                }
                case media_raw_audio_format::B_AUDIO_SHORT:     {
                        return B_TRANSLATE("16 bit integer");
                }
                case media_raw_audio_format::B_AUDIO_FLOAT:     {
                        return B_TRANSLATE("32 bit float");
                }
                case media_raw_audio_format::B_AUDIO_INT: {
                        BString s = "";
                        if (validBits != media_multi_audio_format::wildcard.valid_bits) {
                                static BStringFormat format(
                                        B_TRANSLATE("{0, plural, other{# bit integer}}"));
                                format.Format(s, validBits);
                        } else
                                s = B_TRANSLATE("32 bit integer");
                        return s;
                }
                default: {
                        return B_TRANSLATE("(unknown format)");
                }
        }
}

BString MediaString::forAudioFrameRate(
        float frameRate)
{
        D_METHOD(("MediaString::forAudioFrameRate()\n"));

        if (frameRate == media_raw_audio_format::wildcard.frame_rate) {
                return "*";
        }
        
        BString s;
        s << (frameRate / 1000) << B_TRANSLATE(" kHz");
        return s;
}

BString MediaString::forAudioChannelCount(
        uint32 channelCount)
{
        D_METHOD(("MediaString::forAudioChannelCount()\n"));

        if (channelCount == media_raw_audio_format::wildcard.channel_count) {
                return "*";
        }

        switch (channelCount) {
                case 1: {
                        return B_TRANSLATE("Mono");
                }
                case 2: {
                        return B_TRANSLATE("Stereo");
                }
                default: {
                        BString s = "";
                        static BStringFormat format(
                                B_TRANSLATE("{0, plural, one{# channel}"
                                        "other{# channels}}"));
                        format.Format(s, channelCount);
                        return s;
                }
        }
}

BString MediaString::forAudioByteOrder(
        uint32 byteOrder)
{
        D_METHOD(("MediaString::forAudioByteOrder()\n"));

        if (byteOrder == media_raw_audio_format::wildcard.byte_order) {
                return "*";
        }

        switch (byteOrder) {
                case B_MEDIA_BIG_ENDIAN: {
                        return B_TRANSLATE("Big endian");
                }
                case B_MEDIA_LITTLE_ENDIAN: {
                        return B_TRANSLATE("Little endian");
                }
                default: {
                        return B_TRANSLATE("(unknown byte order)");
                }
        }
}

BString MediaString::forAudioBufferSize(
        size_t bufferSize)
{
        D_METHOD(("MediaString::forAudioBufferSize()\n"));

        if (bufferSize == media_raw_audio_format::wildcard.buffer_size) {
                return "*";
        }

        BString s = "";
        static BStringFormat format(B_TRANSLATE(
                "{0, plural, one{# byte per buffer} other{# bytes per buffer}}"));
        format.Format(s, bufferSize);
        return s;
}

BString MediaString::forAudioChannelMask(
        uint32 channelMask) {
        D_METHOD(("MediaString::forAudioChannelMask()\n"));

        BString list, last;
        bool first = true;

        if (channelMask & B_CHANNEL_LEFT) {
                if (first) {
                        list = B_TRANSLATE("Left");
                        first = false;
                }
        }
        if (channelMask & B_CHANNEL_RIGHT) {
                if (first) {
                        list = B_TRANSLATE("Right");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Right");
                }
        }
        if (channelMask & B_CHANNEL_CENTER) {
                if (first) {
                        list = B_TRANSLATE("Center");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Center");
                }
        }
        if (channelMask & B_CHANNEL_SUB) {
                if (first) {
                        list = B_TRANSLATE("Sub");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Sub");
                }
        }
        if (channelMask & B_CHANNEL_REARLEFT) {
                if (first) {
                        list = B_TRANSLATE("Rear-left");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Rear-left");
                }
        }
        if (channelMask & B_CHANNEL_REARRIGHT) {
                if (first) {
                        list = B_TRANSLATE("Rear-right");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Rear-right");
                }
        }
        if (channelMask & B_CHANNEL_FRONT_LEFT_CENTER) {
                if (first) {
                        list = B_TRANSLATE("Front-left-center");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Front-left-center");
                }
        }
        if (channelMask & B_CHANNEL_FRONT_RIGHT_CENTER) {
                if (first) {
                        list = B_TRANSLATE("Front-right-center");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Front-right-center");
                }
        }
        if (channelMask & B_CHANNEL_BACK_CENTER) {
                if (first) {
                        list = B_TRANSLATE("Back-center");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Back-center");
                }
        }
        if (channelMask & B_CHANNEL_SIDE_LEFT) {
                if (first) {
                        list = B_TRANSLATE("Side-left");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Side-left");
                }
        }
        if (channelMask & B_CHANNEL_SIDE_RIGHT) {
                if (first) {
                        list = B_TRANSLATE("Side-right");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Side-right");
                }
        }
        if (channelMask & B_CHANNEL_TOP_CENTER) {
                if (first) {
                        list = B_TRANSLATE("Top-center");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Top-center");
                }
        }
        if (channelMask & B_CHANNEL_TOP_FRONT_LEFT) {
                if (first) {
                        list = B_TRANSLATE("Top-Front-left");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Top-Front-left");
                }
        }
        if (channelMask & B_CHANNEL_TOP_FRONT_CENTER) {
                if (first) {
                        list = B_TRANSLATE("Top-Front-center");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Top-Front-center");
                }
        }
        if (channelMask & B_CHANNEL_TOP_FRONT_RIGHT) {
                if (first) {
                        list = B_TRANSLATE("Top-Front-right");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Top-Front-right");
                }
        }
        if (channelMask & B_CHANNEL_TOP_BACK_LEFT) {
                if (first) {
                        list = B_TRANSLATE("Top-Back-left");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Top-Back-left");
                }
        }
        if (channelMask & B_CHANNEL_TOP_BACK_CENTER) {
                if (first) {
                        list = B_TRANSLATE("Top-Back-center");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Top-Back-center");
                }
        }
        if (channelMask & B_CHANNEL_TOP_BACK_RIGHT) {
                if (first) {
                        list = B_TRANSLATE("Top-Back-right");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Top-Back-right");
                }
        }
        if (last != "") {
                list << " & " << last;
        }
        if (list == "") {
                list = B_TRANSLATE("(none)");
        }

        return list;
}

BString MediaString::forAudioMatrixMask(
        uint16 matrixMask) {
        D_METHOD(("MediaString::forAudioMatrixMask()\n"));

        switch (matrixMask) {
                case 0:
                        return B_TRANSLATE("(none)");
                case B_MATRIX_PROLOGIC_LR:
                        return B_TRANSLATE("ProLogic LR");
                case B_MATRIX_AMBISONIC_WXYZ:
                        return B_TRANSLATE("Ambisonic WXYZ");
                default:
                        return B_TRANSLATE("(unknown matrix mask)");
        }
}

// -------------------------------------------------------- //
// *** strings for single fields in media_encoded_audio_format 
//         (public)
// -------------------------------------------------------- //

BString MediaString::forAudioBitRate(
        float bitRate)
{
        D_METHOD(("MediaString::forAudioBufferSize()\n"));

        if (bitRate == media_encoded_audio_format::wildcard.bit_rate) {
                return "*";
        }

        BString s = "";
        s << bitRate / 1000.0f << B_TRANSLATE(" kb/s");
        return s;
}

BString MediaString::forAudioFrameSize(
        size_t frameSize)
{
        D_METHOD(("MediaString::forAudioFrameSize()\n"));

        if (frameSize == media_encoded_audio_format::wildcard.frame_size) {
                return "*";
        }

        BString s = "";
        static BStringFormat format(B_TRANSLATE("{0, plural,"
                        "one{# byte per frame}"
                        "other{# bytes per frame}}"));
        format.Format(s, frameSize);
        return s;
}

// -------------------------------------------------------- //
// *** strings for single fields in media_raw_video_format 
//         (public)
// -------------------------------------------------------- //

BString MediaString::forVideoFormat(
        color_space format)
{
        D_METHOD(("MediaString::forVideoFormat()\n"));

        if (format == media_video_display_info::wildcard.format) {
                return "*";
        }

        switch (format) {
                case B_RGB32:
                case B_RGB32_BIG:
                        return B_TRANSLATE("32 bit RGB");
                case B_RGBA32:
                case B_RGBA32_BIG:
                        return B_TRANSLATE("32 bit RGBA");
                case B_RGB24:
                case B_RGB24_BIG:
                        return B_TRANSLATE("24 bit RGB");
                case B_RGB16:
                case B_RGB16_BIG:
                        return B_TRANSLATE("16 bit RGB");
                case B_RGB15:
                case B_RGB15_BIG:
                        return B_TRANSLATE("15 bit RGB");
                case B_RGBA15:
                case B_RGBA15_BIG:
                        return B_TRANSLATE("15 bit RGBA");
                case B_CMAP8:
                        return B_TRANSLATE("8 bit color-index");
                case B_GRAY8:
                        return B_TRANSLATE("8 bit grayscale-index");
                case B_GRAY1:
                        return B_TRANSLATE("Monochrome");
                case B_YUV422:
                        return B_TRANSLATE("YUV422");
                case B_YUV411:
                        return B_TRANSLATE("YUV411");
                case B_YUV420:
                        return B_TRANSLATE("YUV420");
                case B_YUV444:
                        return B_TRANSLATE("YUV444");
                case B_YUV9:
                        return B_TRANSLATE("YUV9");
                case B_YUV12:
                        return B_TRANSLATE("YUV12");
                case B_YCbCr422:
                        return B_TRANSLATE("YCbCr422");
                case B_YCbCr411:
                        return B_TRANSLATE("YCbCr411");
                case B_YCbCr444:
                        return B_TRANSLATE("YCbCr444");
                case B_YCbCr420:
                        return B_TRANSLATE("YCbCr420");
                case B_UVL24:
                        return B_TRANSLATE("24 bit UVL");
                case B_UVL32:
                        return B_TRANSLATE("32 bit UVL");
                case B_UVLA32:
                        return B_TRANSLATE("32 bit UVLA");
                case B_LAB24:
                        return B_TRANSLATE("24 bit LAB");
                case B_LAB32:
                        return B_TRANSLATE("32 bit LAB");
                case B_LABA32:
                        return B_TRANSLATE("32 bit LABA");
                case B_HSI24:
                        return B_TRANSLATE("24 bit HSI");
                case B_HSI32:
                        return B_TRANSLATE("32 bit HSI");
                case B_HSIA32:
                        return B_TRANSLATE("32 bit HSIA");
                case B_HSV24:
                        return B_TRANSLATE("24 bit HSV");
                case B_HSV32:
                        return B_TRANSLATE("32 bit HSV");
                case B_HSVA32:
                        return B_TRANSLATE("32 bit HSVA");
                case B_HLS24:
                        return B_TRANSLATE("24 bit HLS");
                case B_HLS32:
                        return B_TRANSLATE("32 bit HLS");
                case B_HLSA32:
                        return B_TRANSLATE("32 bit HLSA");
                case B_CMY24:
                        return B_TRANSLATE("24 bit CMY");
                case B_CMY32:
                        return B_TRANSLATE("32 bit CMY");
                case B_CMYA32:
                        return B_TRANSLATE("32 bit CMYA");
                case B_CMYK32:
                        return B_TRANSLATE("32 bit CMYK");
                default: {
                        return B_TRANSLATE("(unknown video format)");
                }
        }
}

BString MediaString::forVideoResolution(
        uint32 lineWidth,
        uint32 lineCount)
{
        D_METHOD(("MediaString::forVideoResolution()\n"));

        if ((lineWidth == media_video_display_info::wildcard.line_width)
         || (lineCount == media_video_display_info::wildcard.line_count)) {
                return "*";
        }

        BString s = "";
        s.SetToFormat(B_TRANSLATE_COMMENT("%" B_PRId32" × %" B_PRId32,
                        "The '×' is the Unicode multiplication sign U+00D7"),
                        lineWidth, lineCount);
        return s;
}

BString MediaString::forVideoFieldRate(
        float fieldRate,
        uint32 interlace)
{
        D_METHOD(("MediaString::forVideoFieldRate()\n"));

        if (fieldRate == media_raw_video_format::wildcard.field_rate) {
                return "*";
        }

        BString s = "";
        if (interlace == 1) {
                s << B_TRANSLATE("Non-interlaced ");
        }
        else {
                s << B_TRANSLATE("Interlaced ");
        }
        s << fieldRate << B_TRANSLATE(" Hz");
        if ((fieldRate > 49.9) && (fieldRate < 50.1)) {
                s << B_TRANSLATE(" (PAL)");
        }
        else if (((interlace == 2) && (fieldRate > 59.9) && (fieldRate < 60.0))
                  || ((interlace == 1) && (fieldRate > 29.9) && (fieldRate < 30.0))) {
                s << B_TRANSLATE(" (NTSC)");
        }

        return s;       
}

BString MediaString::forVideoOrientation(
        uint32 orientation)
{
        D_METHOD(("MediaString::forVideoOrientation()\n"));

        if (orientation == media_raw_video_format::wildcard.orientation) {
                return "*";
        }

        switch (orientation) {
                case B_VIDEO_TOP_LEFT_RIGHT: {
                        return B_TRANSLATE("Top to bottom, left to right");
                }
                case B_VIDEO_BOTTOM_LEFT_RIGHT: {
                        return B_TRANSLATE("Bottom to top, left to right");
                }
                default: {
                        return B_TRANSLATE("(unkown video orientation)");
                }
        }
}

BString MediaString::forVideoAspectRatio(
        uint16 pixelWidth,
        uint16 pixelHeight)
{
        D_METHOD(("MediaString::forVideoPixelAspect()\n"));

        if ((pixelWidth == media_raw_video_format::wildcard.pixel_width_aspect)
         || (pixelHeight == media_raw_video_format::wildcard.pixel_height_aspect)) {
                return "*";
        }

        BString s = "";
        s << static_cast<uint32>(pixelWidth);
        s << ":" << static_cast<uint32>(pixelHeight);
        return s;
}

BString MediaString::forVideoActiveLines(
        uint32 firstActive,
        uint32 lastActive)
{
        D_METHOD(("MediaString::forVideoActiveLines()\n"));

        if ((firstActive == media_raw_video_format::wildcard.first_active)
         || (lastActive == media_raw_video_format::wildcard.last_active)) {
                return "*";
        }

        BString s = "";
        s.SetToFormat(
                B_TRANSLATE("Video data between line %" B_PRIu32 " and %" B_PRIu32),
                firstActive, lastActive);
        return s;
}

BString MediaString::forVideoBytesPerRow(
        uint32 bytesPerRow)
{
        D_METHOD(("MediaString::forVideoBytesPerRow()\n"));

        if (bytesPerRow == media_video_display_info::wildcard.bytes_per_row) {
                return "*";
        }

        BString s = "";
        static BStringFormat format(B_TRANSLATE("{0, plural, one{# byte per row}"
                        "other{# bytes per row}}"));
        format.Format(s, bytesPerRow);
        return s;
}

BString MediaString::forVideoOffset(
        uint32 pixelOffset,
        uint32 lineOffset)
{
        D_METHOD(("MediaString::forVideoResolution()\n"));

        BString s = "";
        if (pixelOffset != media_video_display_info::wildcard.pixel_offset) {
                static BStringFormat format(
                        B_TRANSLATE("{0, plural, one{# pixel} other{# pixels}}"));
                format.Format(s, pixelOffset);
        }
        if (lineOffset != media_video_display_info::wildcard.line_offset) {
                if (s != "") {
                        s << ", ";
                }
                BString t = "";
                static BStringFormat format(
                        B_TRANSLATE("{0, plural, one{# line} other{# lines}}"));
                format.Format(t, lineOffset);
                s += t;
        }
        if (s == "") {
                s = "*";
        }
        return s;
}

// -------------------------------------------------------- //
// *** strings for single fields in media_encoded_video_format 
//         (public)
// -------------------------------------------------------- //

BString MediaString::forVideoBitRate(
        float avgBitRate,
        float maxBitRate)
{
        D_METHOD(("MediaString::forVideoBitRate()\n"));

        BString s = "";
        if (avgBitRate != media_encoded_video_format::wildcard.avg_bit_rate) {
                s << avgBitRate / 1000.0f << B_TRANSLATE(" kb/s (avg)");
        }
        if (maxBitRate != media_encoded_video_format::wildcard.max_bit_rate) {
                if (s != "") {
                        s << ", ";
                }
                s << maxBitRate / 1000.0f << B_TRANSLATE(" kb/s (max)");
        }
        if (s == "") {
                s = "*";
        }
        return s;
}

BString MediaString::forVideoFrameSize(
        size_t frameSize)
{
        D_METHOD(("MediaString::forVideoFrameSize()\n"));

        if (frameSize == media_encoded_video_format::wildcard.frame_size) {
                return "*";
        }

        BString s = "";
        static BStringFormat format(B_TRANSLATE("{0, plural,"
                        "one{# byte per frame}"
                        "other{# bytes per frame}}"));
        format.Format(s, frameSize);
        return s;
}

BString MediaString::forVideoHistory(
        int16 forwardHistory,
        int16 backwardHistory)
{
        D_METHOD(("MediaString::forVideoHistory()\n"));

        BString s = "";
        if (forwardHistory != media_encoded_video_format::wildcard.forward_history) {
                static BStringFormat format(B_TRANSLATE("{0, plural,"
                                "one{# frame forward}"
                                "other{# frames forward}}"));
                format.Format(s, static_cast<int32>(forwardHistory));
        }
        if (backwardHistory != media_encoded_video_format::wildcard.backward_history) {
                if (s != "") {
                        s << ", ";
                }
                BString t = "";
                static BStringFormat format(B_TRANSLATE("{0, plural,"
                                "one{# frame backward}"
                                "other{# frames backward}}"));
                format.Format(t, static_cast<int32>(backwardHistory));
                s += t;
        }
        if (s == "") {
                s = "*";
        }
        return s;
}

// -------------------------------------------------------- //
// *** strings for single fields in media_multistream_format 
//         (public)
// -------------------------------------------------------- //

BString MediaString::forMultistreamFormat(
        int32 format)
{
        D_METHOD(("MediaString::forMultistreamFormat()\n"));

        if (format == media_multistream_format::wildcard.format) {
                return "*";
        }

        switch (format) {
                case media_multistream_format::B_VID:
                        return B_TRANSLATE("BeOS video");
                case media_multistream_format::B_AVI:
                        return B_TRANSLATE("AVI");
                case media_multistream_format::B_MPEG1:
                        return B_TRANSLATE("MPEG1");
                case media_multistream_format::B_MPEG2:
                        return B_TRANSLATE("MPEG2");
                case media_multistream_format::B_QUICKTIME:
                        return B_TRANSLATE("QuickTime");
                default:
                        return B_TRANSLATE("(unknown multistream format)");
        }
}

BString MediaString::forMultistreamBitRate(
        float avgBitRate,
        float maxBitRate)
{
        D_METHOD(("MediaString::forMultistreamFormat()\n"));

        BString s = "";
        if (avgBitRate != media_multistream_format::wildcard.avg_bit_rate) {
                s << avgBitRate / 1000.0f << B_TRANSLATE(" kb/s (avg)");
        }
        if (maxBitRate != media_multistream_format::wildcard.max_bit_rate) {
                if (s != "") {
                        s << ", ";
                }
                s << maxBitRate / 1000.0f << B_TRANSLATE(" kb/s (max)");
        }
        if (s == "") {
                s = "*";
        }
        return s;
}

BString MediaString::forMultistreamChunkSize(
        uint32 avgChunkSize,
        uint32 maxChunkSize)
{
        D_METHOD(("MediaString::forMultistreamChunkSize()\n"));

        BString s = "";
        if (avgChunkSize != media_multistream_format::wildcard.avg_chunk_size) {
                static BStringFormat format(B_TRANSLATE("{0, plural,"
                                "one{# byte (avg)}"
                                "other{# bytes (avg)}}"));
                format.Format(s, avgChunkSize);
        }
        if (maxChunkSize != media_multistream_format::wildcard.max_chunk_size) {
                if (s != "") {
                        s << ", ";
                }
                static BStringFormat format(B_TRANSLATE("{0, plural,"
                                "one{# byte (max)}"
                                "other{# bytes (max)}}"));
                format.Format(s, maxChunkSize);
        }
        if (s == "") {
                s = "*";
        }
        return s;
}

BString MediaString::forMultistreamFlags(
        uint32 flags)
{
        D_METHOD(("MediaString::forMultistreamFlags()\n"));

        BString list, last;
        bool first = true;

        if (flags & media_multistream_format::B_HEADER_HAS_FLAGS) {
                if (first) {
                        list = B_TRANSLATE("Header has flags");
                        first = false;
                }
        }
        if (flags & media_multistream_format::B_CLEAN_BUFFERS) {
                if (first) {
                        list = B_TRANSLATE("Clean buffers");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Clean buffers");
                }
        }
        if (flags & media_multistream_format::B_HOMOGENOUS_BUFFERS) {
                if (first) {
                        list = B_TRANSLATE("Homogenous buffers");
                        first = false;
                }
                else {
                        if (last != "")
                                list << ", " << last;
                        last = B_TRANSLATE("Homogenous buffers");
                }
        }

        if (last != "")
                list << " & " << last;

        if (list == "")
                list = B_TRANSLATE("(none)");

        return list;
}

// END -- MediaString.cpp --