Finished implementation of MidiPlayer. Yay!
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8064 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -20,23 +20,77 @@
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <Synth.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include "ScopeView.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ScopeView::ScopeView()
|
||||
: BView(BRect(0, 0, 127, 47), NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP,
|
||||
B_WILL_DRAW | B_PULSE_NEEDED)
|
||||
: BView(BRect(0, 0, 127, 63), NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP,
|
||||
B_WILL_DRAW)
|
||||
{
|
||||
SetViewColor(0, 0, 0);
|
||||
|
||||
enabled = true;
|
||||
haveFile = false;
|
||||
|
||||
sampleCount = (int32) Bounds().Width();
|
||||
leftSamples = new int16[sampleCount];
|
||||
rightSamples = new int16[sampleCount];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ScopeView::~ScopeView()
|
||||
{
|
||||
delete[] leftSamples;
|
||||
delete[] rightSamples;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ScopeView::AttachedToWindow()
|
||||
{
|
||||
finished = false;
|
||||
threadId = spawn_thread(_Thread, "ScopeThread", B_NORMAL_PRIORITY, this);
|
||||
if (threadId >= B_OK)
|
||||
{
|
||||
resume_thread(threadId);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ScopeView::DetachedFromWindow()
|
||||
{
|
||||
if (threadId >= B_OK)
|
||||
{
|
||||
finished = true;
|
||||
status_t exitValue;
|
||||
wait_for_thread(threadId, &exitValue);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ScopeView::Draw(BRect updateRect)
|
||||
{
|
||||
super::Draw(updateRect);
|
||||
|
||||
if (!haveFile)
|
||||
{
|
||||
DrawNoFile();
|
||||
}
|
||||
else if (!enabled)
|
||||
{
|
||||
DrawDisabled();
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawPlaying();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -54,3 +108,94 @@ void ScopeView::SetHaveFile(bool flag)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int32 ScopeView::_Thread(void* data)
|
||||
{
|
||||
return ((ScopeView*) data)->Thread();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int32 ScopeView::Thread()
|
||||
{
|
||||
// Because Pulse() was too slow, I created a thread that tells the
|
||||
// ScopeView to repaint itself. Note that we need to call LockLooper
|
||||
// with a timeout, otherwise we'll deadlock in DetachedFromWindow().
|
||||
|
||||
while (!finished)
|
||||
{
|
||||
if (enabled && haveFile)
|
||||
{
|
||||
if (LockLooperWithTimeout(50000) == B_OK)
|
||||
{
|
||||
Invalidate();
|
||||
UnlockLooper();
|
||||
}
|
||||
}
|
||||
snooze(50000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ScopeView::DrawNoFile()
|
||||
{
|
||||
const char* string = "Drop MIDI file here";
|
||||
|
||||
font_height height;
|
||||
GetFontHeight(&height);
|
||||
|
||||
float strWidth = StringWidth(string);
|
||||
float strHeight = height.ascent + height.descent;
|
||||
|
||||
float x = (Bounds().Width() - strWidth)/2;
|
||||
float y = height.ascent + (Bounds().Height() - strHeight)/2;
|
||||
|
||||
SetHighColor(255, 255, 255);
|
||||
SetLowColor(ViewColor());
|
||||
SetDrawingMode(B_OP_OVER);
|
||||
|
||||
DrawString(string, BPoint(x, y));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ScopeView::DrawDisabled()
|
||||
{
|
||||
SetHighColor(64, 64, 64);
|
||||
|
||||
StrokeLine(
|
||||
BPoint(0, Bounds().Height() / 2),
|
||||
BPoint(Bounds().Width(), Bounds().Height() / 2));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ScopeView::DrawPlaying()
|
||||
{
|
||||
int32 width = (int32) Bounds().Width();
|
||||
int32 height = (int32) Bounds().Height();
|
||||
|
||||
// Scope drawing magic based on code by Michael Pfeiffer.
|
||||
|
||||
int32 size = be_synth->GetAudio(leftSamples, rightSamples, sampleCount);
|
||||
if (size > 0)
|
||||
{
|
||||
SetHighColor(255, 0, 130);
|
||||
SetLowColor(0, 130, 0);
|
||||
#define N 16
|
||||
int32 x, y, sx = 0, f = (height << N) / 65535, dy = height / 2;
|
||||
for (int32 i = 0; i < width; i++)
|
||||
{
|
||||
x = sx / width;
|
||||
y = ((leftSamples[x] * f) >> N) + dy;
|
||||
FillRect(BRect(i, y, i, y));
|
||||
y = ((rightSamples[x] * f) >> N) + dy;
|
||||
FillRect(BRect(i, y, i, y), B_SOLID_LOW);
|
||||
sx += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user