MediaPlayer: reworked info window to use layout API.
* Use BStringViews instead of BTextView - it's more flexible (truncation, and tool tips), and allows for fine grained updates. * The file name and location views are now showing tool tips with their full contents. * Also, its look is now less exotic, if boring.
This commit is contained in:
parent
95fdee0bc0
commit
88fed28aff
@ -2,6 +2,7 @@
|
||||
* InfoWin.cpp - Media Player for the Haiku Operating System
|
||||
*
|
||||
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
|
||||
* Copyright 2015 Axel Dörfler <axeld@pinc-software.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -27,7 +28,9 @@
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <Catalog.h>
|
||||
#include <ControlLook.h>
|
||||
#include <Debug.h>
|
||||
#include <LayoutBuilder.h>
|
||||
#include <MediaDefs.h>
|
||||
#include <MessageFormat.h>
|
||||
#include <Mime.h>
|
||||
@ -43,86 +46,57 @@
|
||||
#include "PlaylistItem.h"
|
||||
|
||||
|
||||
#define NAME "File info"
|
||||
#define MIN_WIDTH 400
|
||||
#define MIN_WIDTH 500
|
||||
|
||||
#define BASE_HEIGHT (32 + 32)
|
||||
|
||||
//const rgb_color kGreen = { 152, 203, 152, 255 };
|
||||
const rgb_color kRed = { 203, 152, 152, 255 };
|
||||
const rgb_color kBlue = { 0, 0, 220, 255 };
|
||||
const rgb_color kGreen = { 171, 221, 161, 255 };
|
||||
const rgb_color kBlack = { 0, 0, 0, 255 };
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
#define B_TRANSLATION_CONTEXT "MediaPlayer-InfoWin"
|
||||
|
||||
// should later draw an icon
|
||||
class InfoView : public BView {
|
||||
public:
|
||||
InfoView(BRect frame, const char* name, float divider);
|
||||
virtual ~InfoView();
|
||||
virtual void Draw(BRect updateRect);
|
||||
|
||||
status_t SetIcon(const PlaylistItem* item);
|
||||
status_t SetIcon(const char* mimeType);
|
||||
void SetGenericIcon();
|
||||
class IconView : public BView {
|
||||
public:
|
||||
IconView(const char* name, int32 iconSize);
|
||||
virtual ~IconView();
|
||||
|
||||
status_t SetIcon(const PlaylistItem* item);
|
||||
status_t SetIcon(const char* mimeType);
|
||||
void SetGenericIcon();
|
||||
|
||||
virtual void GetPreferredSize(float* _width, float* _height);
|
||||
virtual void AttachedToWindow();
|
||||
virtual void Draw(BRect updateRect);
|
||||
|
||||
private:
|
||||
float fDivider;
|
||||
BBitmap* fIconBitmap;
|
||||
BBitmap* fIconBitmap;
|
||||
};
|
||||
|
||||
|
||||
InfoView::InfoView(BRect frame, const char *name, float divider)
|
||||
: BView(frame, name, B_FOLLOW_ALL, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
|
||||
fDivider(divider),
|
||||
fIconBitmap(NULL)
|
||||
IconView::IconView(const char* name, int32 iconSize)
|
||||
:
|
||||
BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
|
||||
fIconBitmap(NULL)
|
||||
{
|
||||
BRect rect(0, 0, B_LARGE_ICON - 1, B_LARGE_ICON - 1);
|
||||
|
||||
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
|
||||
fIconBitmap = new BBitmap(rect, B_RGBA32);
|
||||
#else
|
||||
fIconBitmap = new BBitmap(rect, B_CMAP8);
|
||||
#endif
|
||||
fIconBitmap = new BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1),
|
||||
B_RGBA32);
|
||||
SetExplicitMaxSize(PreferredSize());
|
||||
}
|
||||
|
||||
|
||||
InfoView::~InfoView()
|
||||
IconView::~IconView()
|
||||
{
|
||||
delete fIconBitmap;
|
||||
}
|
||||
|
||||
void
|
||||
InfoView::Draw(BRect updateRect)
|
||||
{
|
||||
SetHighColor(kGreen);
|
||||
BRect r(Bounds());
|
||||
r.right = r.left + fDivider;
|
||||
FillRect(r);
|
||||
|
||||
if (fIconBitmap) {
|
||||
float left = r.left + ( r.right - r.left ) / 2 - B_LARGE_ICON / 2;
|
||||
SetDrawingMode(B_OP_ALPHA);
|
||||
DrawBitmap(fIconBitmap, BPoint(left, r.top + B_LARGE_ICON / 2));
|
||||
}
|
||||
|
||||
SetHighColor(ui_color(B_DOCUMENT_TEXT_COLOR));
|
||||
r.left = r.right;
|
||||
FillRect(r);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
InfoView::SetIcon(const PlaylistItem* item)
|
||||
IconView::SetIcon(const PlaylistItem* item)
|
||||
{
|
||||
return item->GetIcon(fIconBitmap, B_LARGE_ICON);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
InfoView::SetIcon(const char* mimeTypeString)
|
||||
IconView::SetIcon(const char* mimeTypeString)
|
||||
{
|
||||
if (!mimeTypeString)
|
||||
return B_BAD_VALUE;
|
||||
@ -144,7 +118,7 @@ InfoView::SetIcon(const char* mimeTypeString)
|
||||
|
||||
|
||||
void
|
||||
InfoView::SetGenericIcon()
|
||||
IconView::SetGenericIcon()
|
||||
{
|
||||
// get default icon
|
||||
BMimeType genericType(B_FILE_MIME_TYPE);
|
||||
@ -159,67 +133,133 @@ InfoView::SetGenericIcon()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
IconView::GetPreferredSize(float* _width, float* _height)
|
||||
{
|
||||
if (_width != NULL) {
|
||||
*_width = fIconBitmap->Bounds().Width()
|
||||
+ 2 * be_control_look->DefaultItemSpacing();
|
||||
}
|
||||
if (_height != NULL) {
|
||||
*_height = fIconBitmap->Bounds().Height()
|
||||
+ 2 * be_control_look->DefaultItemSpacing();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
IconView::AttachedToWindow()
|
||||
{
|
||||
if (Parent() != NULL)
|
||||
SetViewColor(Parent()->ViewColor());
|
||||
else
|
||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
IconView::Draw(BRect updateRect)
|
||||
{
|
||||
BRect rect(Bounds());
|
||||
|
||||
if (fIconBitmap != NULL) {
|
||||
// Draw bitmap centered within the view
|
||||
SetDrawingMode(B_OP_ALPHA);
|
||||
DrawBitmap(fIconBitmap, BPoint(rect.left
|
||||
+ (rect.Width() - fIconBitmap->Bounds().Width()) / 2,
|
||||
rect.top + (rect.Height() - fIconBitmap->Bounds().Height()) / 2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
InfoWin::InfoWin(BPoint leftTop, Controller* controller)
|
||||
:
|
||||
BWindow(BRect(leftTop.x, leftTop.y, leftTop.x + MIN_WIDTH - 1,
|
||||
leftTop.y + 300), B_TRANSLATE(NAME), B_TITLED_WINDOW,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE | B_NOT_ZOOMABLE),
|
||||
leftTop.y + 300), B_TRANSLATE("File info"), B_TITLED_WINDOW,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS | B_NOT_ZOOMABLE),
|
||||
fController(controller),
|
||||
fControllerObserver(new ControllerObserver(this,
|
||||
OBSERVE_FILE_CHANGES | OBSERVE_TRACK_CHANGES | OBSERVE_STAT_CHANGES))
|
||||
{
|
||||
BRect rect = Bounds();
|
||||
|
||||
// accomodate for big fonts
|
||||
float div = max_c(2 * 32, be_plain_font->StringWidth(
|
||||
B_TRANSLATE("Display Mode")) + 10);
|
||||
|
||||
fInfoView = new InfoView(rect, "background", div);
|
||||
fInfoView->SetViewColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR));
|
||||
AddChild(fInfoView);
|
||||
fIconView = new IconView("background", B_LARGE_ICON);
|
||||
|
||||
fFilenameView = _CreateInfo("filename");
|
||||
BFont bigFont(be_plain_font);
|
||||
bigFont.SetSize(bigFont.Size() + 6);
|
||||
font_height fh;
|
||||
bigFont.GetHeight(&fh);
|
||||
fFilenameView = new BStringView(
|
||||
BRect(div + 10, 20, rect.right - 10, 20 + fh.ascent + 5),
|
||||
"filename", "");
|
||||
AddChild(fFilenameView);
|
||||
bigFont.SetSize(bigFont.Size() * 1.5f);
|
||||
fFilenameView->SetFont(&bigFont);
|
||||
fFilenameView->SetViewColor(fInfoView->ViewColor());
|
||||
fFilenameView->SetLowColor(fInfoView->ViewColor());
|
||||
#ifdef B_BEOS_VERSION_DANO /* maybe we should support that as well ? */
|
||||
fFilenameView->SetTruncation(B_TRUNCATE_END);
|
||||
#endif
|
||||
|
||||
rect.top = BASE_HEIGHT;
|
||||
// Create info views
|
||||
|
||||
BRect lr(rect);
|
||||
BRect cr(rect);
|
||||
lr.right = div - 1;
|
||||
cr.left = div + 1;
|
||||
BRect tr;
|
||||
tr = lr.OffsetToCopy(0, 0).InsetByCopy(5, 1);
|
||||
fLabelsView = new BTextView(lr, "labels", tr, B_FOLLOW_BOTTOM);
|
||||
fLabelsView->SetViewColor(kGreen);
|
||||
fLabelsView->SetAlignment(B_ALIGN_RIGHT);
|
||||
fLabelsView->SetWordWrap(false);
|
||||
AddChild(fLabelsView);
|
||||
tr = cr.OffsetToCopy(0, 0).InsetByCopy(10, 1);
|
||||
fContentsView = new BTextView(cr, "contents", tr, B_FOLLOW_BOTTOM);
|
||||
fContentsView->SetWordWrap(false);
|
||||
AddChild(fContentsView);
|
||||
BStringView* containerLabel = _CreateLabel("containerLabel",
|
||||
B_TRANSLATE("Container"));
|
||||
fContainerInfo = _CreateInfo("container");
|
||||
|
||||
fLabelsView->MakeSelectable();
|
||||
fContentsView->MakeSelectable();
|
||||
fVideoSeparator = _CreateSeparator();
|
||||
fVideoLabel = _CreateLabel("videoLabel", B_TRANSLATE("Video"));
|
||||
fVideoFormatInfo = _CreateInfo("videoFormat");
|
||||
fVideoConfigInfo = _CreateInfo("videoConfig");
|
||||
fDisplayModeLabel = _CreateLabel("displayModeLabel",
|
||||
B_TRANSLATE("Display mode"));
|
||||
fDisplayModeInfo = _CreateInfo("displayMode");
|
||||
|
||||
fAudioSeparator = _CreateSeparator();
|
||||
fAudioLabel = _CreateLabel("audioLabel", B_TRANSLATE("Audio"));
|
||||
fAudioFormatInfo = _CreateInfo("audioFormat");
|
||||
fAudioConfigInfo = _CreateInfo("audioConfig");
|
||||
|
||||
BStringView* durationLabel = _CreateLabel("durationLabel",
|
||||
B_TRANSLATE("Duration"));
|
||||
fDurationInfo = _CreateInfo("duration");
|
||||
|
||||
BStringView* locationLabel = _CreateLabel("locationLabel",
|
||||
B_TRANSLATE("Location"));
|
||||
fLocationInfo = _CreateInfo("location");
|
||||
|
||||
fCopyrightSeparator = _CreateSeparator();
|
||||
fCopyrightLabel = _CreateLabel("copyrightLabel", B_TRANSLATE("Copyright"));
|
||||
fCopyrightInfo = _CreateInfo("copyright");
|
||||
|
||||
BLayoutBuilder::Group<>(this, B_VERTICAL)
|
||||
.SetInsets(B_USE_DEFAULT_SPACING)
|
||||
.AddGroup(B_HORIZONTAL)
|
||||
.Add(fIconView, 0)
|
||||
.Add(fFilenameView, 1)
|
||||
.End()
|
||||
.AddGrid(2, 13)
|
||||
.Add(containerLabel, 0, 0)
|
||||
.Add(fContainerInfo, 1, 0)
|
||||
.Add(fVideoSeparator, 0, 1)
|
||||
.Add(fVideoLabel, 0, 2)
|
||||
.Add(fVideoFormatInfo, 1, 2)
|
||||
.Add(fVideoConfigInfo, 1, 3)
|
||||
.Add(fDisplayModeLabel, 0, 4)
|
||||
.Add(fDisplayModeInfo, 1, 4)
|
||||
.Add(fAudioSeparator, 0, 5)
|
||||
.Add(fAudioLabel, 0, 6)
|
||||
.Add(fAudioFormatInfo, 1, 6)
|
||||
.Add(fAudioConfigInfo, 1, 7)
|
||||
.Add(_CreateSeparator(), 0, 8)
|
||||
.Add(durationLabel, 0, 9)
|
||||
.Add(fDurationInfo, 1, 9)
|
||||
.Add(_CreateSeparator(), 0, 10)
|
||||
.Add(locationLabel, 0, 11)
|
||||
.Add(fLocationInfo, 1, 11)
|
||||
.Add(fCopyrightSeparator, 0, 12)
|
||||
.Add(fCopyrightLabel, 0, 12)
|
||||
.Add(fCopyrightInfo, 1, 12)
|
||||
.SetColumnWeight(0, 0)
|
||||
.SetColumnWeight(1, 1)
|
||||
.SetSpacing(B_USE_DEFAULT_SPACING, 0)
|
||||
.SetExplicitMinSize(BSize(MIN_WIDTH, B_SIZE_UNSET));
|
||||
|
||||
fController->AddListener(fControllerObserver);
|
||||
Update();
|
||||
|
||||
UpdateSizeLimits();
|
||||
|
||||
// Move window on screen if needed
|
||||
BScreen screen(this);
|
||||
if (screen.Frame().bottom < Frame().bottom)
|
||||
@ -238,15 +278,6 @@ InfoWin::~InfoWin()
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
InfoWin::FrameResized(float newWidth, float newHeight)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoWin::MessageReceived(BMessage* msg)
|
||||
{
|
||||
@ -257,14 +288,14 @@ InfoWin::MessageReceived(BMessage* msg)
|
||||
Update(INFO_ALL);
|
||||
break;
|
||||
case MSG_CONTROLLER_VIDEO_TRACK_CHANGED:
|
||||
Update(/*INFO_VIDEO | INFO_STATS*/INFO_ALL);
|
||||
Update(INFO_VIDEO | INFO_STATS);
|
||||
break;
|
||||
case MSG_CONTROLLER_AUDIO_TRACK_CHANGED:
|
||||
Update(/*INFO_AUDIO | INFO_STATS*/INFO_ALL);
|
||||
Update(INFO_AUDIO | INFO_STATS);
|
||||
break;
|
||||
case MSG_CONTROLLER_VIDEO_STATS_CHANGED:
|
||||
case MSG_CONTROLLER_AUDIO_STATS_CHANGED:
|
||||
Update(/*INFO_STATS*/INFO_ALL);
|
||||
Update(INFO_STATS);
|
||||
break;
|
||||
default:
|
||||
BWindow::MessageReceived(msg);
|
||||
@ -294,226 +325,302 @@ InfoWin::Pulse()
|
||||
|
||||
|
||||
void
|
||||
InfoWin::ResizeToPreferred()
|
||||
InfoWin::Update(uint32 which)
|
||||
{
|
||||
if (!fController->Lock())
|
||||
return;
|
||||
|
||||
if ((which & INFO_FILE) != 0)
|
||||
_UpdateFile();
|
||||
|
||||
// video track format information
|
||||
if ((which & INFO_VIDEO) != 0)
|
||||
_UpdateVideo();
|
||||
|
||||
// audio track format information
|
||||
if ((which & INFO_AUDIO) != 0)
|
||||
_UpdateAudio();
|
||||
|
||||
// statistics
|
||||
if ((which & INFO_STATS) != 0) {
|
||||
_UpdateDuration();
|
||||
// TODO: demux/video/audio/... perfs (Kb/info)
|
||||
}
|
||||
|
||||
if ((which & INFO_TRANSPORT) != 0) {
|
||||
// Transport protocol info (file, http, rtsp, ...)
|
||||
}
|
||||
|
||||
if ((which & INFO_COPYRIGHT)!=0)
|
||||
_UpdateCopyright();
|
||||
|
||||
fController->Unlock();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoWin::Update(uint32 which)
|
||||
InfoWin::_UpdateFile()
|
||||
{
|
||||
printf("InfoWin::Update(0x%08" B_PRIx32 ")\n", which);
|
||||
fLabelsView->SetText("");
|
||||
fContentsView->SetText("");
|
||||
fLabelsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kBlue);
|
||||
fLabelsView->Insert(" ");
|
||||
fContentsView->SetFontAndColor(be_plain_font, B_FONT_ALL);
|
||||
// fContentsView->Insert("");
|
||||
bool iconSet = false;
|
||||
if (fController->HasFile()) {
|
||||
const PlaylistItem* item = fController->Item();
|
||||
iconSet = fIconView->SetIcon(item) == B_OK;
|
||||
media_file_format fileFormat;
|
||||
status_t status = fController->GetFileFormatInfo(&fileFormat);
|
||||
if (status == B_OK) {
|
||||
fContainerInfo->SetText(fileFormat.pretty_name);
|
||||
if (!iconSet)
|
||||
iconSet = fIconView->SetIcon(fileFormat.mime_type) == B_OK;
|
||||
} else
|
||||
fContainerInfo->SetText(strerror(status));
|
||||
|
||||
if (!fController->Lock())
|
||||
return;
|
||||
BString info;
|
||||
if (fController->GetLocation(&info) != B_OK)
|
||||
info = B_TRANSLATE("<unknown>");
|
||||
fLocationInfo->SetText(info.String());
|
||||
fLocationInfo->SetToolTip(info.String());
|
||||
|
||||
fLabelsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kRed);
|
||||
if (fController->GetName(&info) != B_OK || info.IsEmpty())
|
||||
info = B_TRANSLATE("<unnamed media>");
|
||||
fFilenameView->SetText(info.String());
|
||||
fFilenameView->SetToolTip(info.String());
|
||||
} else {
|
||||
fFilenameView->SetText(B_TRANSLATE("<no media>"));
|
||||
fContainerInfo->SetText("-");
|
||||
fLocationInfo->SetText("-");
|
||||
}
|
||||
|
||||
status_t err;
|
||||
// video track format information
|
||||
if ((which & INFO_VIDEO) && fController->VideoTrackCount() > 0) {
|
||||
BString label = B_TRANSLATE("Video");
|
||||
fLabelsView->Insert(label << "\n\n\n");
|
||||
BString s;
|
||||
if (!iconSet)
|
||||
fIconView->SetGenericIcon();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoWin::_UpdateVideo()
|
||||
{
|
||||
bool visible = fController->VideoTrackCount() > 0;
|
||||
if (visible) {
|
||||
BString info;
|
||||
media_format format;
|
||||
media_raw_video_format videoFormat = {};
|
||||
err = fController->GetEncodedVideoFormat(&format);
|
||||
if (err < B_OK) {
|
||||
s << "(" << strerror(err) << ")\n";
|
||||
status_t status = fController->GetEncodedVideoFormat(&format);
|
||||
if (status != B_OK) {
|
||||
info << "(" << strerror(status) << ")\n";
|
||||
} else if (format.type == B_MEDIA_ENCODED_VIDEO) {
|
||||
videoFormat = format.u.encoded_video.output;
|
||||
media_codec_info mci;
|
||||
err = fController->GetVideoCodecInfo(&mci);
|
||||
if (err < B_OK) {
|
||||
s << B_TRANSLATE("Haiku Media Kit: ") << strerror(err);
|
||||
status = fController->GetVideoCodecInfo(&mci);
|
||||
if (status != B_OK) {
|
||||
if (format.user_data_type == B_CODEC_TYPE_INFO) {
|
||||
s << (char *)format.user_data << " "
|
||||
info << (char *)format.user_data << " "
|
||||
<< B_TRANSLATE("(not supported)");
|
||||
}
|
||||
} else
|
||||
info = strerror(status);
|
||||
} else
|
||||
s << mci.pretty_name; //<< "(" << mci.short_name << ")";
|
||||
info << mci.pretty_name; //<< "(" << mci.short_name << ")";
|
||||
} else if (format.type == B_MEDIA_RAW_VIDEO) {
|
||||
videoFormat = format.u.raw_video;
|
||||
s << B_TRANSLATE("raw video");
|
||||
info << B_TRANSLATE("raw video");
|
||||
} else
|
||||
s << B_TRANSLATE("unknown format");
|
||||
s << "\n";
|
||||
s << format.Width() << " x " << format.Height();
|
||||
info << B_TRANSLATE("unknown format");
|
||||
|
||||
fVideoFormatInfo->SetText(info.String());
|
||||
|
||||
info.SetToFormat("%" B_PRIu32 " x %" B_PRIu32, format.Width(),
|
||||
format.Height());
|
||||
|
||||
// encoded has output as 1st field...
|
||||
char fpsString[20];
|
||||
snprintf(fpsString, sizeof(fpsString), B_TRANSLATE("%.3f fps"),
|
||||
videoFormat.field_rate);
|
||||
s << ", " << fpsString << "\n\n";
|
||||
fContentsView->Insert(s.String());
|
||||
info << ", " << fpsString;
|
||||
|
||||
fVideoConfigInfo->SetText(info.String());
|
||||
|
||||
if (fController->IsOverlayActive())
|
||||
fDisplayModeInfo->SetText(B_TRANSLATE("Overlay"));
|
||||
else
|
||||
fDisplayModeInfo->SetText(B_TRANSLATE("DrawBitmap"));
|
||||
}
|
||||
|
||||
// audio track format information
|
||||
if ((which & INFO_AUDIO) && fController->AudioTrackCount() > 0) {
|
||||
BString label = B_TRANSLATE("Audio");
|
||||
fLabelsView->Insert(label << "\n\n\n");
|
||||
BString s;
|
||||
fVideoSeparator->SetVisible(visible);
|
||||
_SetVisible(fVideoLabel, visible);
|
||||
_SetVisible(fVideoFormatInfo, visible);
|
||||
_SetVisible(fVideoConfigInfo, visible);
|
||||
_SetVisible(fDisplayModeLabel, visible);
|
||||
_SetVisible(fDisplayModeInfo, visible);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoWin::_UpdateAudio()
|
||||
{
|
||||
bool visible = fController->AudioTrackCount() > 0;
|
||||
if (visible) {
|
||||
BString info;
|
||||
media_format format;
|
||||
media_raw_audio_format audioFormat = {};
|
||||
err = fController->GetEncodedAudioFormat(&format);
|
||||
//string_for_format(format, buf, sizeof(buf));
|
||||
//printf("%s\n", buf);
|
||||
if (err < 0) {
|
||||
s << "(" << strerror(err) << ")\n";
|
||||
|
||||
status_t status = fController->GetEncodedAudioFormat(&format);
|
||||
if (status != B_OK) {
|
||||
info << "(" << strerror(status) << ")\n";
|
||||
} else if (format.type == B_MEDIA_ENCODED_AUDIO) {
|
||||
audioFormat = format.u.encoded_audio.output;
|
||||
media_codec_info mci;
|
||||
err = fController->GetAudioCodecInfo(&mci);
|
||||
if (err < 0) {
|
||||
s << B_TRANSLATE("Haiku Media Kit: ") << strerror(err);
|
||||
status = fController->GetAudioCodecInfo(&mci);
|
||||
if (status != B_OK) {
|
||||
if (format.user_data_type == B_CODEC_TYPE_INFO) {
|
||||
s << (char *)format.user_data << " "
|
||||
info << (char *)format.user_data << " "
|
||||
<< B_TRANSLATE("(not supported)");
|
||||
}
|
||||
} else
|
||||
info = strerror(status);
|
||||
} else
|
||||
s << mci.pretty_name; //<< "(" << mci.short_name << ")";
|
||||
info = mci.pretty_name;
|
||||
} else if (format.type == B_MEDIA_RAW_AUDIO) {
|
||||
audioFormat = format.u.raw_audio;
|
||||
s << B_TRANSLATE("raw audio");
|
||||
info = B_TRANSLATE("raw audio");
|
||||
} else
|
||||
s << B_TRANSLATE("unknown format");
|
||||
s << "\n";
|
||||
info = B_TRANSLATE("unknown format");
|
||||
|
||||
fAudioFormatInfo->SetText(info.String());
|
||||
|
||||
uint32 bitsPerSample = 8 * (audioFormat.format
|
||||
& media_raw_audio_format::B_AUDIO_SIZE_MASK);
|
||||
uint32 channelCount = audioFormat.channel_count;
|
||||
float sr = audioFormat.frame_rate;
|
||||
|
||||
info.Truncate(0);
|
||||
|
||||
if (bitsPerSample > 0) {
|
||||
char bitString[20];
|
||||
snprintf(bitString, sizeof(bitString), B_TRANSLATE("%d Bit"),
|
||||
bitsPerSample);
|
||||
s << bitString << " ";
|
||||
info << bitString << " ";
|
||||
}
|
||||
|
||||
static BMessageFormat channelFormat(B_TRANSLATE(
|
||||
"{0, plural, =1{Mono} =2{Stereo} other{# Channels}}"));
|
||||
channelFormat.Format(s, channelCount);
|
||||
channelFormat.Format(info, channelCount);
|
||||
|
||||
s << ", ";
|
||||
info << ", ";
|
||||
if (sr > 0.0) {
|
||||
char rateString[20];
|
||||
snprintf(rateString, sizeof(rateString),
|
||||
B_TRANSLATE("%.3f kHz"), sr / 1000);
|
||||
s << rateString;
|
||||
info << rateString;
|
||||
} else {
|
||||
BString rateString = B_TRANSLATE("%d kHz");
|
||||
rateString.ReplaceFirst("%d", "??");
|
||||
s << rateString;
|
||||
info << rateString;
|
||||
}
|
||||
if (format.type == B_MEDIA_ENCODED_AUDIO) {
|
||||
float br = format.u.encoded_audio.bit_rate;
|
||||
char string[20] = "";
|
||||
if (br > 0.0)
|
||||
s << ", " << string_for_rate(br, string, sizeof(string));
|
||||
}
|
||||
s << "\n\n";
|
||||
fContentsView->Insert(s.String());
|
||||
}
|
||||
|
||||
// statistics
|
||||
if ((which & INFO_STATS) && fController->HasFile()) {
|
||||
BString label = B_TRANSLATE("Duration");
|
||||
fLabelsView->Insert(label << "\n");
|
||||
BString s;
|
||||
bigtime_t d = fController->TimeDuration();
|
||||
bigtime_t v;
|
||||
|
||||
//s << d << "µs; ";
|
||||
|
||||
d /= 1000;
|
||||
|
||||
v = d / (3600 * 1000);
|
||||
d = d % (3600 * 1000);
|
||||
bool hours = v > 0;
|
||||
if (hours)
|
||||
s << v << ":";
|
||||
v = d / (60 * 1000);
|
||||
d = d % (60 * 1000);
|
||||
s << v << ":";
|
||||
v = d / 1000;
|
||||
if (v < 10)
|
||||
s << '0';
|
||||
s << v;
|
||||
if (hours)
|
||||
s << " " << B_TRANSLATE_COMMENT("h", "Hours");
|
||||
else
|
||||
s << " " << B_TRANSLATE_COMMENT("min", "Minutes");
|
||||
s << "\n";
|
||||
fContentsView->Insert(s.String());
|
||||
// TODO: demux/video/audio/... perfs (Kb/s)
|
||||
|
||||
BString content = B_TRANSLATE("Display mode");
|
||||
fLabelsView->Insert(content << "\n");
|
||||
if (fController->IsOverlayActive()) {
|
||||
content = B_TRANSLATE("Overlay");
|
||||
fContentsView->Insert(content << "\n");
|
||||
} else {
|
||||
content = B_TRANSLATE("DrawBitmap");
|
||||
fContentsView->Insert(content << "\n");
|
||||
info << ", " << string_for_rate(br, string, sizeof(string));
|
||||
}
|
||||
|
||||
fLabelsView->Insert("\n");
|
||||
fContentsView->Insert("\n");
|
||||
fAudioConfigInfo->SetText(info.String());
|
||||
}
|
||||
|
||||
if (which & INFO_TRANSPORT) {
|
||||
// Transport protocol info (file, http, rtsp, ...)
|
||||
}
|
||||
|
||||
if (which & INFO_FILE) {
|
||||
bool iconSet = false;
|
||||
if (fController->HasFile()) {
|
||||
const PlaylistItem* item = fController->Item();
|
||||
iconSet = fInfoView->SetIcon(item) == B_OK;
|
||||
media_file_format fileFormat;
|
||||
BString s;
|
||||
if (fController->GetFileFormatInfo(&fileFormat) == B_OK) {
|
||||
BString label = B_TRANSLATE("Container");
|
||||
fLabelsView->Insert(label << "\n");
|
||||
s << fileFormat.pretty_name;
|
||||
s << "\n";
|
||||
fContentsView->Insert(s.String());
|
||||
if (!iconSet)
|
||||
iconSet = fInfoView->SetIcon(fileFormat.mime_type) == B_OK;
|
||||
} else
|
||||
fContentsView->Insert("\n");
|
||||
BString label = B_TRANSLATE("Location");
|
||||
fLabelsView->Insert(label << "\n");
|
||||
if (fController->GetLocation(&s) < B_OK)
|
||||
s = B_TRANSLATE("<unknown>");
|
||||
s << "\n";
|
||||
fContentsView->Insert(s.String());
|
||||
if (fController->GetName(&s) < B_OK)
|
||||
s = B_TRANSLATE("<unnamed media>");
|
||||
fFilenameView->SetText(s.String());
|
||||
} else {
|
||||
fFilenameView->SetText(B_TRANSLATE("<no media>"));
|
||||
}
|
||||
if (!iconSet)
|
||||
fInfoView->SetGenericIcon();
|
||||
}
|
||||
|
||||
if ((which & INFO_COPYRIGHT) && fController->HasFile()) {
|
||||
BString s;
|
||||
if (fController->GetCopyright(&s) == B_OK && s.Length() > 0) {
|
||||
BString label = B_TRANSLATE("Copyright");
|
||||
fLabelsView->Insert(label << "\n\n");
|
||||
s << "\n\n";
|
||||
fContentsView->Insert(s.String());
|
||||
}
|
||||
}
|
||||
|
||||
fController->Unlock();
|
||||
|
||||
ResizeToPreferred();
|
||||
fAudioSeparator->SetVisible(visible);
|
||||
_SetVisible(fAudioLabel, visible);
|
||||
_SetVisible(fAudioFormatInfo, visible);
|
||||
_SetVisible(fAudioConfigInfo, visible);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoWin::_UpdateDuration()
|
||||
{
|
||||
if (!fController->HasFile()) {
|
||||
fDurationInfo->SetText("-");
|
||||
return;
|
||||
}
|
||||
|
||||
BString info;
|
||||
|
||||
bigtime_t d = fController->TimeDuration() / 1000;
|
||||
bigtime_t v = d / (3600 * 1000);
|
||||
d = d % (3600 * 1000);
|
||||
bool hours = v > 0;
|
||||
if (hours)
|
||||
info << v << ":";
|
||||
v = d / (60 * 1000);
|
||||
d = d % (60 * 1000);
|
||||
info << v << ":";
|
||||
v = d / 1000;
|
||||
if (v < 10)
|
||||
info << '0';
|
||||
info << v;
|
||||
if (hours)
|
||||
info << " " << B_TRANSLATE_COMMENT("h", "Hours");
|
||||
else
|
||||
info << " " << B_TRANSLATE_COMMENT("min", "Minutes");
|
||||
|
||||
fDurationInfo->SetText(info.String());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoWin::_UpdateCopyright()
|
||||
{
|
||||
BString info;
|
||||
|
||||
bool visible = fController->HasFile()
|
||||
&& fController->GetCopyright(&info) == B_OK && !info.IsEmpty();
|
||||
if (visible)
|
||||
fCopyrightInfo->SetText(info.String());
|
||||
|
||||
fCopyrightSeparator->SetVisible(visible);
|
||||
_SetVisible(fCopyrightLabel, visible);
|
||||
_SetVisible(fCopyrightInfo, visible);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BStringView*
|
||||
InfoWin::_CreateLabel(const char* name, const char* label)
|
||||
{
|
||||
static const rgb_color kLabelColor = tint_color(
|
||||
ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_3_TINT);
|
||||
|
||||
BStringView* view = new BStringView(name, label);
|
||||
view->SetAlignment(B_ALIGN_RIGHT);
|
||||
view->SetHighColor(kLabelColor);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
BStringView*
|
||||
InfoWin::_CreateInfo(const char* name)
|
||||
{
|
||||
BStringView* view = new BStringView(name, "");
|
||||
view->SetExplicitMinSize(BSize(200, B_SIZE_UNSET));
|
||||
view->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
|
||||
view->SetTruncation(B_TRUNCATE_SMART);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
BLayoutItem*
|
||||
InfoWin::_CreateSeparator()
|
||||
{
|
||||
return BSpaceLayoutItem::CreateVerticalStrut(
|
||||
be_control_look->ComposeSpacing(B_USE_HALF_ITEM_SPACING));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoWin::_SetVisible(BView* view, bool visible)
|
||||
{
|
||||
bool hidden = view->IsHidden(view);
|
||||
if (hidden && visible)
|
||||
view->Show();
|
||||
else if (!hidden && !visible)
|
||||
view->Hide();
|
||||
}
|
||||
|
@ -24,11 +24,12 @@
|
||||
#include <Window.h>
|
||||
|
||||
|
||||
class BLayoutItem;
|
||||
class BStringView;
|
||||
class BTextView;
|
||||
class Controller;
|
||||
class ControllerObserver;
|
||||
class InfoView;
|
||||
class IconView;
|
||||
|
||||
|
||||
#define INFO_STATS 0x00000001
|
||||
@ -47,22 +48,49 @@ public:
|
||||
Controller* controller);
|
||||
virtual ~InfoWin();
|
||||
|
||||
virtual void FrameResized(float newWidth, float newHeight);
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual bool QuitRequested();
|
||||
virtual void Pulse();
|
||||
|
||||
void ResizeToPreferred();
|
||||
void Update(uint32 which = INFO_ALL);
|
||||
|
||||
private:
|
||||
void _UpdateFile();
|
||||
void _UpdateVideo();
|
||||
void _UpdateAudio();
|
||||
void _UpdateDuration();
|
||||
void _UpdateCopyright();
|
||||
|
||||
BStringView* _CreateLabel(const char* name,
|
||||
const char* label);
|
||||
BStringView* _CreateInfo(const char* name);
|
||||
BLayoutItem* _CreateSeparator();
|
||||
void _SetVisible(BView* view, bool visible);
|
||||
|
||||
private:
|
||||
Controller* fController;
|
||||
ControllerObserver* fControllerObserver;
|
||||
|
||||
InfoView* fInfoView;
|
||||
IconView* fIconView;
|
||||
BStringView* fFilenameView;
|
||||
BTextView* fLabelsView;
|
||||
BTextView* fContentsView;
|
||||
|
||||
BStringView* fContainerInfo;
|
||||
BLayoutItem* fVideoSeparator;
|
||||
BStringView* fVideoLabel;
|
||||
BStringView* fVideoFormatInfo;
|
||||
BStringView* fVideoConfigInfo;
|
||||
BStringView* fDisplayModeLabel;
|
||||
BStringView* fDisplayModeInfo;
|
||||
BLayoutItem* fAudioSeparator;
|
||||
BStringView* fAudioLabel;
|
||||
BStringView* fAudioFormatInfo;
|
||||
BStringView* fAudioConfigInfo;
|
||||
BStringView* fDurationInfo;
|
||||
BStringView* fLocationInfo;
|
||||
BLayoutItem* fCopyrightSeparator;
|
||||
BStringView* fCopyrightLabel;
|
||||
BStringView* fCopyrightInfo;
|
||||
};
|
||||
|
||||
|
||||
#endif // __FILE_INFO_WIN_H
|
||||
|
Loading…
Reference in New Issue
Block a user