Add a position-seeker replicant (PositionView)
This commit is contained in:
parent
00f9ecb0cb
commit
44eda8ab54
1
Makefile
1
Makefile
|
@ -36,6 +36,7 @@ SRCS = src/App.cpp \
|
|||
src/LyricsView.cpp \
|
||||
src/MainWindow.cpp \
|
||||
src/MediaPlayer.cpp \
|
||||
src/PositionView.cpp \
|
||||
src/ReplicantView.cpp \
|
||||
src/Song.cpp \
|
||||
src/Util.cpp \
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "CoverView.h"
|
||||
#include "LyricsView.h"
|
||||
#include "PositionView.h"
|
||||
#include "VolumeView.h"
|
||||
|
||||
|
||||
|
@ -32,6 +33,7 @@ MainWindow::_InitInterface()
|
|||
BView* controlsView = new BView("Controls", B_WILL_DRAW);
|
||||
BLayoutBuilder::Group<>(controlsView, B_VERTICAL)
|
||||
.Add(new VolumeView(BRect(BPoint(0,0), BSize(100.0, 20.0))))
|
||||
.Add(new PositionView(BRect(BPoint(0,0), BSize(100.0, 20.0))))
|
||||
.AddGlue()
|
||||
.End();
|
||||
|
||||
|
|
|
@ -54,6 +54,15 @@ MediaPlayer::IsPlaying()
|
|||
}
|
||||
|
||||
|
||||
int64
|
||||
MediaPlayer::Duration()
|
||||
{
|
||||
BMessage send, reply;
|
||||
_ScriptingCall("Duration", &send, &reply, MP_CURRENT_TRACK);
|
||||
return reply.GetInt64("result", -1);
|
||||
}
|
||||
|
||||
|
||||
int64
|
||||
MediaPlayer::Position()
|
||||
{
|
||||
|
@ -63,6 +72,15 @@ MediaPlayer::Position()
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
MediaPlayer::SetPosition(int64 position)
|
||||
{
|
||||
BMessage send(B_SET_PROPERTY), reply;
|
||||
send.AddInt64("data", position);
|
||||
_ScriptingCall("Position", &send, &reply);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
MediaPlayer::Volume()
|
||||
{
|
||||
|
|
|
@ -29,7 +29,9 @@ public:
|
|||
|
||||
|
||||
bool IsPlaying();
|
||||
int64 Duration();
|
||||
int64 Position();
|
||||
void SetPosition(int64 position);
|
||||
float Volume();
|
||||
void SetVolume(float volume);
|
||||
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright 2022, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "PositionView.h"
|
||||
|
||||
#include <ControlLook.h>
|
||||
|
||||
#include "MediaPlayer.h"
|
||||
|
||||
|
||||
const char* kPositionDesc = "PositionView is a replicant that shows the position of currently playing item.";
|
||||
|
||||
// The same color MediaPlayer uses, interface/SeekSlider
|
||||
static const rgb_color kThumbRed = (rgb_color){ 255, 52, 52, 255 };
|
||||
|
||||
static const uint32 POSITION_CHANGED = 'vvch';
|
||||
|
||||
|
||||
SeekSlider::SeekSlider(BRect frame, const char* name, BMessage* message, int32 minValue,
|
||||
int32 maxValue, orientation posture, uint32 resizingMode, uint32 flags)
|
||||
:
|
||||
BSlider(frame, name, NULL, message, minValue, maxValue, posture, B_TRIANGLE_THUMB, resizingMode,
|
||||
flags)
|
||||
{
|
||||
rgb_color fillColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
|
||||
B_DARKEN_3_TINT);
|
||||
UseFillColor(true, &fillColor);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SeekSlider::DrawThumb()
|
||||
{
|
||||
if (!IsEnabled())
|
||||
return;
|
||||
|
||||
BRect frame = ThumbFrame();
|
||||
be_control_look->DrawSliderTriangle(this, frame, frame, kThumbRed, 0,
|
||||
B_HORIZONTAL);
|
||||
}
|
||||
|
||||
|
||||
PositionView::PositionView(BRect frame)
|
||||
:
|
||||
ReplicantView(frame, "Position", B_FOLLOW_RIGHT, B_FOLLOW_LEFT_RIGHT,
|
||||
B_WILL_DRAW | B_DRAW_ON_CHILDREN | B_NAVIGABLE | B_FRAME_EVENTS)
|
||||
{
|
||||
fDescription.SetTo(kPositionDesc);
|
||||
|
||||
_InitInterface();
|
||||
Pulse();
|
||||
}
|
||||
|
||||
|
||||
PositionView::PositionView(BMessage* data)
|
||||
:
|
||||
ReplicantView(data)
|
||||
{
|
||||
fDescription.SetTo(kPositionDesc);
|
||||
|
||||
// For some reason, the BSlider gets archived with a wacko frame― better to just nuke it.
|
||||
fSlider = dynamic_cast<SeekSlider*>(FindView("seekSlider"));
|
||||
delete fSlider;
|
||||
|
||||
_InitInterface();
|
||||
Pulse();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PositionView::Archive(BMessage* data, bool deep) const
|
||||
{
|
||||
status_t status = ReplicantView::Archive(data, deep);
|
||||
|
||||
data->AddString("class", "PositionView");
|
||||
data->AddString("add_on", APP_SIGNATURE);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
PositionView*
|
||||
PositionView::Instantiate(BMessage* data)
|
||||
{
|
||||
if (!validate_instantiation(data, "PositionView"))
|
||||
return NULL;
|
||||
return new PositionView(data);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PositionView::AttachedToWindow()
|
||||
{
|
||||
fSlider->SetTarget(this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PositionView::MessageReceived(BMessage* msg)
|
||||
{
|
||||
switch (msg->what) {
|
||||
case POSITION_CHANGED:
|
||||
fMediaPlayer->SetPosition(_SliderToPosition(fSlider->Position(),
|
||||
fMediaPlayer->Duration()));
|
||||
break;
|
||||
case B_MOUSE_WHEEL_CHANGED:
|
||||
{
|
||||
float scroll = 0.0f;
|
||||
if ((msg->FindFloat("be:wheel_delta_x", &scroll) == B_OK && scroll != 0.0f)
|
||||
|| (msg->FindFloat("be:wheel_delta_y", &scroll) == B_OK && scroll != 0.0f))
|
||||
fSlider->SetPosition(fSlider->Position() + scroll * -0.03);
|
||||
fMediaPlayer->SetPosition(_SliderToPosition(fSlider->Position(),
|
||||
fMediaPlayer->Duration()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ReplicantView::MessageReceived(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PositionView::Pulse()
|
||||
{
|
||||
int64 position = fMediaPlayer->Position();
|
||||
int64 duration = fMediaPlayer->Duration();
|
||||
if (duration > 0) {
|
||||
SetInactive(false);
|
||||
fSlider->SetPosition(_PositionToSlider(position, duration));
|
||||
} else
|
||||
SetInactive(true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PositionView::SetInactive(bool inactive)
|
||||
{
|
||||
fSlider->SetEnabled(!inactive);
|
||||
|
||||
if (inactive && fTransparentInactivity && !fSlider->IsHidden())
|
||||
fSlider->Hide();
|
||||
else if ((!inactive || !fTransparentInactivity) && fSlider->IsHidden())
|
||||
fSlider->Show();
|
||||
|
||||
ReplicantView::SetInactive(inactive);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PositionView::_InitInterface()
|
||||
{
|
||||
SetViewColor(B_TRANSPARENT_COLOR);
|
||||
|
||||
fSlider = new SeekSlider(BRect(), "seekSlider", NULL, 0, 1000, B_HORIZONTAL,
|
||||
B_FOLLOW_LEFT_RIGHT);
|
||||
fSlider->SetModificationMessage(new BMessage(POSITION_CHANGED));
|
||||
fSlider->SetViewColor(B_TRANSPARENT_COLOR);
|
||||
AddChild(fSlider);
|
||||
|
||||
float height = 20.0;
|
||||
fSlider->GetPreferredSize(NULL, &height);
|
||||
SetExplicitMaxSize(BSize(B_SIZE_UNSET, height + 16));
|
||||
fSlider->ResizeTo(Frame().Size());
|
||||
}
|
||||
|
||||
|
||||
int64
|
||||
PositionView::_SliderToPosition(float sliderPos, int64 duration)
|
||||
{
|
||||
return duration * sliderPos;
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
PositionView::_PositionToSlider(int64 position, int64 duration)
|
||||
{
|
||||
return (double)position / (double)duration;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2022, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef POSITIONVIEW_H
|
||||
#define POSITIONVIEW_H
|
||||
|
||||
#include <Slider.h>
|
||||
|
||||
#include "ReplicantView.h"
|
||||
|
||||
|
||||
class SeekSlider : public BSlider {
|
||||
public:
|
||||
SeekSlider(BRect frame, const char* name, BMessage* message, int32 minValue,
|
||||
int32 maxValue, orientation posture,
|
||||
uint32 resizingMode = B_FOLLOW_LEFT_TOP,
|
||||
uint32 flags = B_NAVIGABLE | B_WILL_DRAW | B_FRAME_EVENTS);
|
||||
|
||||
virtual void DrawThumb();
|
||||
};
|
||||
|
||||
|
||||
class PositionView : public ReplicantView {
|
||||
public:
|
||||
PositionView(BRect frame);
|
||||
PositionView(BMessage* archive);
|
||||
|
||||
virtual status_t Archive(BMessage* data, bool deep = true) const;
|
||||
static PositionView* Instantiate(BMessage* data);
|
||||
|
||||
void AttachedToWindow();
|
||||
|
||||
virtual void MessageReceived(BMessage* msg);
|
||||
virtual void Pulse();
|
||||
|
||||
virtual void SetInactive(bool inactive);
|
||||
|
||||
private:
|
||||
void _InitInterface();
|
||||
int64 _SliderToPosition(float volume, int64 duration);
|
||||
float _PositionToSlider(int64 position, int64 duration);
|
||||
|
||||
SeekSlider* fSlider;
|
||||
};
|
||||
|
||||
#endif // POSITIONVIEW_H
|
Ŝarĝante…
Reference in New Issue