* now supports several audio formats for VUView and ScopeView
* cleanup git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31760 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -9,12 +9,13 @@
|
||||
#include "RecorderWindow.h"
|
||||
|
||||
|
||||
RecorderApp::RecorderApp(const char * signature) :
|
||||
BApplication(signature), fRecorderWin(NULL)
|
||||
RecorderApp::RecorderApp(const char* signature)
|
||||
: BApplication(signature), fRecorderWin(NULL)
|
||||
{
|
||||
fRecorderWin = new RecorderWindow();
|
||||
}
|
||||
|
||||
|
||||
RecorderApp::~RecorderApp()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
class RecorderWindow;
|
||||
|
||||
class RecorderApp : public BApplication {
|
||||
public:
|
||||
RecorderApp(const char * signature);
|
||||
virtual ~RecorderApp();
|
||||
status_t InitCheck();
|
||||
private:
|
||||
RecorderWindow* fRecorderWin;
|
||||
public:
|
||||
RecorderApp(const char * signature);
|
||||
virtual ~RecorderApp();
|
||||
status_t InitCheck();
|
||||
private:
|
||||
RecorderWindow* fRecorderWin;
|
||||
};
|
||||
|
||||
#endif /* RECORDERAPP_H */
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
* Copyright 2005, Jérôme Duval. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers)
|
||||
* Inspired by SoundCapture from Be newsletter (Media Kit Basics:
|
||||
* Consumers and Producers)
|
||||
*/
|
||||
|
||||
#include <Application.h>
|
||||
@@ -61,7 +62,8 @@ static const float MIN_HEIGHT = 336.0f;
|
||||
static const float XPOS = 100.0f;
|
||||
static const float YPOS = 200.0f;
|
||||
|
||||
#define FOURCC(a,b,c,d) ((((uint32)(d)) << 24) | (((uint32)(c)) << 16) | (((uint32)(b)) << 8) | ((uint32)(a)))
|
||||
#define FOURCC(a,b,c,d) ((((uint32)(d)) << 24) | (((uint32)(c)) << 16) \
|
||||
| (((uint32)(b)) << 8) | ((uint32)(a)))
|
||||
|
||||
struct riff_struct
|
||||
{
|
||||
@@ -97,8 +99,8 @@ struct wave_struct
|
||||
|
||||
|
||||
RecorderWindow::RecorderWindow() :
|
||||
BWindow(BRect(XPOS,YPOS,XPOS+MIN_WIDTH,YPOS+MIN_HEIGHT), "SoundRecorder", B_TITLED_WINDOW,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_NOT_V_RESIZABLE | B_NOT_ZOOMABLE),
|
||||
BWindow(BRect(XPOS,YPOS,XPOS+MIN_WIDTH,YPOS+MIN_HEIGHT), "SoundRecorder",
|
||||
B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_NOT_V_RESIZABLE | B_NOT_ZOOMABLE),
|
||||
fPlayer(NULL),
|
||||
fSoundList(NULL),
|
||||
fPlayFile(NULL),
|
||||
@@ -135,7 +137,7 @@ RecorderWindow::RecorderWindow() :
|
||||
|
||||
RecorderWindow::~RecorderWindow()
|
||||
{
|
||||
// The sound consumer and producer are Nodes; it has to be Release()d and the Roster
|
||||
// The sound consumer and producer are Nodes; it has to be released and the Roster
|
||||
// will reap it when it's done.
|
||||
if (fRecordNode) {
|
||||
fRecordNode->Release();
|
||||
@@ -154,9 +156,9 @@ RecorderWindow::~RecorderWindow()
|
||||
// Clean up items in list view.
|
||||
if (fSoundList) {
|
||||
fSoundList->DeselectAll();
|
||||
for (int ix=0; ix<fSoundList->CountItems(); ix++) {
|
||||
WINDOW((stderr, "clean up item %d\n", ix+1));
|
||||
SoundListItem * item = dynamic_cast<SoundListItem *>(fSoundList->ItemAt(ix));
|
||||
for (int i = 0; i < fSoundList->CountItems(); i++) {
|
||||
WINDOW((stderr, "clean up item %d\n", i+1));
|
||||
SoundListItem* item = dynamic_cast<SoundListItem *>(fSoundList->ItemAt(i));
|
||||
if (item) {
|
||||
if (item->IsTemp()) {
|
||||
item->Entry().Remove(); // delete temp file
|
||||
@@ -241,8 +243,8 @@ RecorderWindow::InitWindow()
|
||||
// Create the window header with controls
|
||||
BRect r(Bounds());
|
||||
r.bottom = r.top + 175;
|
||||
BBox *background = new BBox(r, "_background", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
|
||||
B_WILL_DRAW|B_FRAME_EVENTS|B_NAVIGABLE_JUMP, B_NO_BORDER);
|
||||
BBox *background = new BBox(r, "_background", B_FOLLOW_LEFT_RIGHT
|
||||
| B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP, B_NO_BORDER);
|
||||
AddChild(background);
|
||||
|
||||
|
||||
@@ -265,7 +267,8 @@ RecorderWindow::InitWindow()
|
||||
r.right -= 26;
|
||||
r.top = 115;
|
||||
r.bottom = r.top + 30;
|
||||
fTrackSlider = new TrackSlider(r, "trackSlider", new BMessage(POSITION_CHANGED), B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP);
|
||||
fTrackSlider = new TrackSlider(r, "trackSlider", new BMessage(POSITION_CHANGED),
|
||||
B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
|
||||
background->AddChild(fTrackSlider);
|
||||
|
||||
BRect buttonRect;
|
||||
@@ -274,16 +277,16 @@ RecorderWindow::InitWindow()
|
||||
buttonRect = BRect(BPoint(0,0), kSkipButtonSize);
|
||||
buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-7, 25));
|
||||
fRewindButton = new TransportButton(buttonRect, "Rewind",
|
||||
kSkipBackBitmapBits, kPressedSkipBackBitmapBits, kDisabledSkipBackBitmapBits,
|
||||
new BMessage(REWIND));
|
||||
kSkipBackBitmapBits, kPressedSkipBackBitmapBits,
|
||||
kDisabledSkipBackBitmapBits, new BMessage(REWIND));
|
||||
background->AddChild(fRewindButton);
|
||||
|
||||
// Button for stopping recording or playback
|
||||
buttonRect = BRect(BPoint(0,0), kStopButtonSize);
|
||||
buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-48, 25));
|
||||
fStopButton = new TransportButton(buttonRect, "Stop",
|
||||
kStopButtonBitmapBits, kPressedStopButtonBitmapBits, kDisabledStopButtonBitmapBits,
|
||||
new BMessage(STOP));
|
||||
kStopButtonBitmapBits, kPressedStopButtonBitmapBits,
|
||||
kDisabledStopButtonBitmapBits, new BMessage(STOP));
|
||||
background->AddChild(fStopButton);
|
||||
|
||||
// Button for starting playback of selected sound
|
||||
@@ -297,8 +300,8 @@ RecorderWindow::InitWindow()
|
||||
buttonRect = BRect(BPoint(0,0), kSkipButtonSize);
|
||||
buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-133, 25));
|
||||
fForwardButton = new TransportButton(buttonRect, "Forward",
|
||||
kSkipForwardBitmapBits, kPressedSkipForwardBitmapBits, kDisabledSkipForwardBitmapBits,
|
||||
new BMessage(FORWARD));
|
||||
kSkipForwardBitmapBits, kPressedSkipForwardBitmapBits,
|
||||
kDisabledSkipForwardBitmapBits, new BMessage(FORWARD));
|
||||
background->AddChild(fForwardButton);
|
||||
|
||||
// Button to start recording (or waiting for sound)
|
||||
@@ -312,7 +315,8 @@ RecorderWindow::InitWindow()
|
||||
buttonRect = BRect(BPoint(0,0), kDiskButtonSize);
|
||||
buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-250, 21));
|
||||
fSaveButton = new TransportButton(buttonRect, "Save",
|
||||
kDiskButtonBitmapsBits, kPressedDiskButtonBitmapsBits, kDisabledDiskButtonBitmapsBits, new BMessage(SAVE));
|
||||
kDiskButtonBitmapsBits, kPressedDiskButtonBitmapsBits,
|
||||
kDisabledDiskButtonBitmapsBits, new BMessage(SAVE));
|
||||
fSaveButton->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP);
|
||||
background->AddChild(fSaveButton);
|
||||
|
||||
@@ -327,13 +331,15 @@ RecorderWindow::InitWindow()
|
||||
|
||||
buttonRect = BRect(BPoint(0,0), kSpeakerIconBitmapSize);
|
||||
buttonRect.OffsetTo(background->Bounds().RightBottom() - BPoint(121, 17));
|
||||
SpeakerView *speakerView = new SpeakerView(buttonRect, B_FOLLOW_LEFT | B_FOLLOW_TOP);
|
||||
SpeakerView *speakerView = new SpeakerView(buttonRect,
|
||||
B_FOLLOW_LEFT | B_FOLLOW_TOP);
|
||||
speakerView->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP);
|
||||
background->AddChild(speakerView);
|
||||
|
||||
buttonRect = BRect(BPoint(0,0), BPoint(84, 19));
|
||||
buttonRect.OffsetTo(background->Bounds().RightBottom() - BPoint(107, 20));
|
||||
fVolumeSlider = new VolumeSlider(buttonRect, "volumeSlider", B_FOLLOW_LEFT | B_FOLLOW_TOP);
|
||||
fVolumeSlider = new VolumeSlider(buttonRect, "volumeSlider",
|
||||
B_FOLLOW_LEFT | B_FOLLOW_TOP);
|
||||
fVolumeSlider->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP);
|
||||
background->AddChild(fVolumeSlider);
|
||||
|
||||
@@ -362,8 +368,8 @@ RecorderWindow::InitWindow()
|
||||
fSoundList = new SoundListView(r, "Sound List", B_FOLLOW_ALL);
|
||||
fSoundList->SetSelectionMessage(new BMessage(SOUND_SELECTED));
|
||||
fSoundList->SetViewColor(216, 216, 216);
|
||||
BScrollView *scroller = new BScrollView("scroller", fSoundList, B_FOLLOW_ALL,
|
||||
0, false, true, B_FANCY_BORDER);
|
||||
BScrollView *scroller = new BScrollView("scroller", fSoundList,
|
||||
B_FOLLOW_ALL, 0, false, true, B_FANCY_BORDER);
|
||||
fBottomBox->AddChild(scroller);
|
||||
|
||||
r = fBottomBox->Bounds();
|
||||
@@ -425,18 +431,19 @@ RecorderWindow::InitWindow()
|
||||
char selected_name[B_MEDIA_NAME_LENGTH] = "Default Input";
|
||||
BMessage * msg;
|
||||
BMenuItem * item;
|
||||
for (int ix=0; ix<real_count; ix++) {
|
||||
for (int i = 0; i < real_count; i++) {
|
||||
msg = new BMessage(INPUT_SELECTED);
|
||||
msg->AddData("node", B_RAW_TYPE, &dni[ix], sizeof(dni[ix]));
|
||||
item = new BMenuItem(dni[ix].name, msg);
|
||||
msg->AddData("node", B_RAW_TYPE, &dni[i], sizeof(dni[i]));
|
||||
item = new BMenuItem(dni[i].name, msg);
|
||||
popup->AddItem(item);
|
||||
media_node_id ni[12];
|
||||
int32 ni_count = 12;
|
||||
error = fRoster->GetInstancesFor(dni[ix].addon, dni[ix].flavor_id, ni, &ni_count);
|
||||
error = fRoster->GetInstancesFor(dni[i].addon, dni[i].flavor_id,
|
||||
ni, &ni_count);
|
||||
if (error == B_OK)
|
||||
for (int iy=0; iy<ni_count; iy++)
|
||||
if (ni[iy] == fAudioInputNode.node) {
|
||||
strcpy(selected_name, dni[ix].name);
|
||||
for (int j = 0; j < ni_count; j++)
|
||||
if (ni[j] == fAudioInputNode.node) {
|
||||
strcpy(selected_name, dni[i].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -572,7 +579,8 @@ RecorderWindow::MessageReceived(BMessage * message)
|
||||
}
|
||||
if (message->FindInt64("right", &right) == B_OK) {
|
||||
if (fPlayTrack)
|
||||
fPlayLimit = MIN(fPlayFrames, (off_t)(right * fPlayFormat.u.raw_audio.frame_rate/1000000LL));
|
||||
fPlayLimit = MIN(fPlayFrames,
|
||||
(off_t)(right * fPlayFormat.u.raw_audio.frame_rate/1000000LL));
|
||||
fScopeView->SetRightTime(right);
|
||||
}
|
||||
if (message->FindInt64("left", &left) == B_OK) {
|
||||
@@ -632,7 +640,8 @@ RecorderWindow::Record(BMessage * message)
|
||||
}
|
||||
// Reserve space on disk (creates fewer fragments)
|
||||
err = fRecFile.SetSize(4 * fRecordFormat.u.raw_audio.channel_count
|
||||
* fRecordFormat.u.raw_audio.frame_rate * (fRecordFormat.u.raw_audio.format & 0xf));
|
||||
* fRecordFormat.u.raw_audio.frame_rate * (fRecordFormat.u.raw_audio.format
|
||||
& media_raw_audio_format::B_AUDIO_SIZE_MASK));
|
||||
if (err < B_OK) {
|
||||
ErrorAlert("record a sound that long", err);
|
||||
fRecEntry.Remove();
|
||||
@@ -653,10 +662,11 @@ RecorderWindow::Record(BMessage * message)
|
||||
}
|
||||
|
||||
// And get it going...
|
||||
bigtime_t then = fRecordNode->TimeSource()->Now()+50000LL;
|
||||
bigtime_t then = fRecordNode->TimeSource()->Now() + 50000LL;
|
||||
fRoster->StartNode(fRecordNode->Node(), then);
|
||||
if (fAudioInputNode.kind & B_TIME_SOURCE) {
|
||||
fRoster->StartNode(fAudioInputNode, fRecordNode->TimeSource()->RealTimeFor(then, 0));
|
||||
fRoster->StartNode(fAudioInputNode,
|
||||
fRecordNode->TimeSource()->RealTimeFor(then, 0));
|
||||
}
|
||||
else {
|
||||
fRoster->StartNode(fAudioInputNode, then);
|
||||
@@ -684,7 +694,8 @@ RecorderWindow::Play(BMessage * message)
|
||||
return;
|
||||
}
|
||||
|
||||
fPlayLimit = MIN(fPlayFrames, (off_t)(fTrackSlider->RightTime() * fPlayFormat.u.raw_audio.frame_rate / 1000000LL));
|
||||
fPlayLimit = MIN(fPlayFrames, (off_t)(fTrackSlider->RightTime()
|
||||
* fPlayFormat.u.raw_audio.frame_rate / 1000000LL));
|
||||
fPlayTrack->SeekToTime(fTrackSlider->MainTime());
|
||||
fPlayFrame = fPlayTrack->CurrentFrame();
|
||||
|
||||
@@ -813,7 +824,8 @@ RecorderWindow::Selected(BMessage * message)
|
||||
return;
|
||||
status_t err = UpdatePlayFile(pItem, true);
|
||||
if (err != B_OK) {
|
||||
ErrorAlert("recognize this file as a media file", err == B_MEDIA_NO_HANDLER ? B_OK : err);
|
||||
ErrorAlert("recognize this file as a media file",
|
||||
err == B_MEDIA_NO_HANDLER ? B_OK : err);
|
||||
RemoveCurrentSoundItem();
|
||||
}
|
||||
UpdateButtons();
|
||||
@@ -828,11 +840,13 @@ RecorderWindow::MakeRecordConnection(const media_node & input)
|
||||
int32 count = 0;
|
||||
status_t err = fRoster->GetFreeOutputsFor(input, &fAudioOutput, 1, &count, B_MEDIA_RAW_AUDIO);
|
||||
if (err < B_OK) {
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't get free outputs from audio input node\n"));
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
|
||||
" couldn't get free outputs from audio input node\n"));
|
||||
return err;
|
||||
}
|
||||
if (count < 1) {
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): no free outputs from audio input node\n"));
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
|
||||
" no free outputs from audio input node\n"));
|
||||
return B_BUSY;
|
||||
}
|
||||
|
||||
@@ -843,11 +857,13 @@ RecorderWindow::MakeRecordConnection(const media_node & input)
|
||||
// TODO: explain this
|
||||
err = fRoster->GetFreeInputsFor(fRecordNode->Node(), &fRecInput, 1, &count, B_MEDIA_RAW_AUDIO);
|
||||
if (err < B_OK) {
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't get free inputs for sound recorder\n"));
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
|
||||
" couldn't get free inputs for sound recorder\n"));
|
||||
return err;
|
||||
}
|
||||
if (count < 1) {
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): no free inputs for sound recorder\n"));
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
|
||||
" no free inputs for sound recorder\n"));
|
||||
return B_BUSY;
|
||||
}
|
||||
|
||||
@@ -863,14 +879,16 @@ RecorderWindow::MakeRecordConnection(const media_node & input)
|
||||
media_node use_time_source;
|
||||
BTimeSource * tsobj = fRoster->MakeTimeSourceFor(input);
|
||||
if (! tsobj) {
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't clone time source from audio input node\n"));
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
|
||||
" couldn't clone time source from audio input node\n"));
|
||||
return B_MEDIA_BAD_NODE;
|
||||
}
|
||||
|
||||
// Apply the time source in effect to our own Node.
|
||||
err = fRoster->SetTimeSourceFor(fRecordNode->Node().node, tsobj->Node().node);
|
||||
if (err < B_OK) {
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't set the sound recorder's time source\n"));
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
|
||||
" couldn't set the sound recorder's time source\n"));
|
||||
tsobj->Release();
|
||||
return err;
|
||||
}
|
||||
@@ -882,7 +900,8 @@ RecorderWindow::MakeRecordConnection(const media_node & input)
|
||||
// Tell the consumer where we want data to go.
|
||||
err = fRecordNode->SetHooks(RecordFile, NotifyRecordFile, this);
|
||||
if (err < B_OK) {
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't set the sound recorder's hook functions\n"));
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
|
||||
" couldn't set the sound recorder's hook functions\n"));
|
||||
tsobj->Release();
|
||||
return err;
|
||||
}
|
||||
@@ -890,7 +909,8 @@ RecorderWindow::MakeRecordConnection(const media_node & input)
|
||||
// Using the same structs for input and output is OK in BMediaRoster::Connect().
|
||||
err = fRoster->Connect(fAudioOutput.source, fRecInput.destination, &fRecordFormat, &fAudioOutput, &fRecInput);
|
||||
if (err < B_OK) {
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): failed to connect sound recorder to audio input node.\n"));
|
||||
CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
|
||||
" failed to connect sound recorder to audio input node.\n"));
|
||||
tsobj->Release();
|
||||
fRecordNode->SetHooks(0, 0, 0);
|
||||
return err;
|
||||
@@ -913,7 +933,8 @@ RecorderWindow::BreakRecordConnection()
|
||||
// If we are the last connection, the Node will stop automatically since it
|
||||
// has nowhere to send data to.
|
||||
err = fRoster->StopNode(fRecInput.node, 0);
|
||||
err = fRoster->Disconnect(fAudioOutput.node.node, fAudioOutput.source, fRecInput.node.node, fRecInput.destination);
|
||||
err = fRoster->Disconnect(fAudioOutput.node.node, fAudioOutput.source,
|
||||
fRecInput.node.node, fRecInput.destination);
|
||||
fAudioOutput.source = media_source::null;
|
||||
fRecInput.destination = media_destination::null;
|
||||
return err;
|
||||
@@ -1175,8 +1196,8 @@ RecorderWindow::RemoveCurrentSoundItem() {
|
||||
|
||||
|
||||
void
|
||||
RecorderWindow::RecordFile(void * cookie, bigtime_t timestamp,
|
||||
void * data, size_t size, const media_raw_audio_format & format)
|
||||
RecorderWindow::RecordFile(void* cookie, bigtime_t timestamp,
|
||||
void* data, size_t size, const media_raw_audio_format &format)
|
||||
{
|
||||
// Callback called from the SoundConsumer when receiving buffers.
|
||||
RecorderWindow * window = (RecorderWindow *)cookie;
|
||||
@@ -1185,7 +1206,7 @@ RecorderWindow::RecordFile(void * cookie, bigtime_t timestamp,
|
||||
// Write the data to file (we don't buffer or guard file access
|
||||
// or anything)
|
||||
window->fRecFile.WriteAt(window->fRecSize, data, size);
|
||||
window->fVUView->ComputeNextLevel(data, size);
|
||||
window->fVUView->ComputeLevels(data, size, format.format);
|
||||
window->fRecSize += size;
|
||||
}
|
||||
}
|
||||
@@ -1204,7 +1225,8 @@ RecorderWindow::NotifyRecordFile(void * cookie, int32 code, ...)
|
||||
|
||||
|
||||
void
|
||||
RecorderWindow::PlayFile(void * cookie, void * data, size_t size, const media_raw_audio_format & format)
|
||||
RecorderWindow::PlayFile(void * cookie, void * data, size_t size,
|
||||
const media_raw_audio_format & format)
|
||||
{
|
||||
// Callback called from the SoundProducer when producing buffers.
|
||||
RecorderWindow * window = (RecorderWindow *)cookie;
|
||||
@@ -1219,7 +1241,7 @@ RecorderWindow::PlayFile(void * cookie, void * data, size_t size, const media_ra
|
||||
}
|
||||
int64 frames = 0;
|
||||
window->fPlayTrack->ReadFrames(data, &frames);
|
||||
window->fVUView->ComputeNextLevel(data, size/frame_size);
|
||||
window->fVUView->ComputeLevels(data, size / frame_size, format.format);
|
||||
window->fPlayFrame += size/frame_size;
|
||||
window->PostMessage(UPDATE_TRACKSLIDER);
|
||||
} else {
|
||||
@@ -1229,7 +1251,8 @@ RecorderWindow::PlayFile(void * cookie, void * data, size_t size, const media_ra
|
||||
}
|
||||
|
||||
void
|
||||
RecorderWindow::NotifyPlayFile(void * cookie, BSoundPlayer::sound_player_notification code, ...)
|
||||
RecorderWindow::NotifyPlayFile(void * cookie,
|
||||
BSoundPlayer::sound_player_notification code, ...)
|
||||
{
|
||||
if ((code == BSoundPlayer::B_STOPPED) || (code == BSoundPlayer::B_SOUND_DONE)) {
|
||||
RecorderWindow * window = (RecorderWindow *)cookie;
|
||||
@@ -1300,7 +1323,8 @@ RecorderWindow::CopyTarget(BMessage *msg)
|
||||
|
||||
// write data
|
||||
bigtime_t diffTime = fTrackSlider->RightTime() - fTrackSlider->LeftTime();
|
||||
int64 framesToWrite = (int64) (diffTime * fPlayFormat.u.raw_audio.frame_rate / 1000000LL);
|
||||
int64 framesToWrite = (int64) (diffTime
|
||||
* fPlayFormat.u.raw_audio.frame_rate / 1000000LL);
|
||||
int32 frameSize = (fPlayFormat.u.raw_audio.format & 0xf)
|
||||
* fPlayFormat.u.raw_audio.channel_count;
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
* Copyright 2005, Jérôme Duval. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers)
|
||||
* Inspired by SoundCapture from Be newsletter (Media Kit Basics:
|
||||
* Consumers and Producers)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -14,6 +15,8 @@
|
||||
#include "DrawingTidbits.h"
|
||||
#include "ScopeView.h"
|
||||
|
||||
#define SAMPLES_COUNT 20000
|
||||
|
||||
//#define TRACE 1
|
||||
#ifdef TRACE
|
||||
#define TRACE(x...) printf(x)
|
||||
@@ -28,13 +31,11 @@ ScopeView::ScopeView(BRect rect, uint32 resizeFlags)
|
||||
fBitmapView(NULL),
|
||||
fIsRendering(false),
|
||||
fMediaTrack(NULL),
|
||||
fQuitting(false),
|
||||
fMainTime(0),
|
||||
fRightTime(1000000),
|
||||
fLeftTime(0),
|
||||
fTotalTime(1000000)
|
||||
{
|
||||
fRenderSem = create_sem(0, "scope rendering");
|
||||
fHeight = Bounds().Height();
|
||||
}
|
||||
|
||||
@@ -75,7 +76,8 @@ ScopeView::Draw(BRect updateRect)
|
||||
|
||||
float x = 2;
|
||||
if (fTotalTime !=0)
|
||||
x = 2 + (fMainTime - fLeftTime) * (bounds.right - 2) / (fRightTime - fLeftTime);
|
||||
x += (fMainTime - fLeftTime) * (bounds.right - 2)
|
||||
/ (fRightTime - fLeftTime);
|
||||
SetHighColor(60,255,40);
|
||||
StrokeLine(BPoint(x, bounds.top), BPoint(x, bounds.bottom));
|
||||
|
||||
@@ -86,7 +88,9 @@ ScopeView::Draw(BRect updateRect)
|
||||
void
|
||||
ScopeView::Run()
|
||||
{
|
||||
fThreadId = spawn_thread(&RenderLaunch, "Scope view", B_NORMAL_PRIORITY, this);
|
||||
fRenderSem = create_sem(0, "scope rendering");
|
||||
fThreadId = spawn_thread(&RenderLaunch, "Scope view", B_NORMAL_PRIORITY,
|
||||
this);
|
||||
if (fThreadId < 0)
|
||||
return;
|
||||
resume_thread(fThreadId);
|
||||
@@ -96,7 +100,6 @@ void
|
||||
ScopeView::Quit()
|
||||
{
|
||||
delete_sem(fRenderSem);
|
||||
fQuitting = true;
|
||||
snooze(10000);
|
||||
kill_thread(fThreadId);
|
||||
}
|
||||
@@ -112,51 +115,80 @@ ScopeView::RenderLaunch(void *data)
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename U>
|
||||
void
|
||||
ScopeView::ComputeRendering()
|
||||
{
|
||||
int64 framesCount = fMediaTrack->CountFrames() / SAMPLES_COUNT;
|
||||
T samples[fPlayFormat.u.raw_audio.buffer_size / (fPlayFormat.u.raw_audio.format
|
||||
& media_raw_audio_format::B_AUDIO_SIZE_MASK)];
|
||||
int64 frames = 0;
|
||||
U sum = 0;
|
||||
int64 sumCount = 0;
|
||||
float middle = fHeight / 2;
|
||||
int32 previewMax = 0;
|
||||
//fMediaTrack->SeekToFrame(&frames);
|
||||
|
||||
TRACE("begin computing\n");
|
||||
|
||||
int32 previewIndex = 0;
|
||||
|
||||
while (fIsRendering && fMediaTrack->ReadFrames(samples, &frames) == B_OK) {
|
||||
//TRACE("reading block\n");
|
||||
int64 framesIndex = 0;
|
||||
|
||||
while (framesIndex < frames) {
|
||||
for (; framesIndex < frames && sumCount < framesCount;
|
||||
framesIndex++, sumCount++) {
|
||||
sum += samples[2 * framesIndex];
|
||||
sum += samples[2 * framesIndex + 1];
|
||||
}
|
||||
|
||||
if (previewIndex >= SAMPLES_COUNT)
|
||||
break;
|
||||
|
||||
if (sumCount >= framesCount) {
|
||||
//TRACE("computing block %ld, sumCount %ld\n", previewIndex, sumCount);
|
||||
fPreview[previewIndex] = (int32)(sum
|
||||
/ fPlayFormat.u.raw_audio.channel_count / framesCount);
|
||||
if (previewMax < fPreview[previewIndex])
|
||||
previewMax = fPreview[previewIndex];
|
||||
sumCount = 0;
|
||||
sum = 0;
|
||||
previewIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < SAMPLES_COUNT; i++)
|
||||
fPreview[i] = (int32)(fPreview[i] * 1.0 / previewMax * middle + middle);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScopeView::RenderLoop()
|
||||
{
|
||||
while (!fQuitting) {
|
||||
if (acquire_sem(fRenderSem)!=B_OK)
|
||||
continue;
|
||||
|
||||
while (acquire_sem(fRenderSem) == B_OK) {
|
||||
fIsRendering = true;
|
||||
|
||||
//int32 frameSize = (fPlayFormat.u.raw_audio.format & 0xf) * fPlayFormat.u.raw_audio.channel_count;
|
||||
int64 totalFrames = fMediaTrack->CountFrames();
|
||||
int16 samples[fPlayFormat.u.raw_audio.buffer_size / (fPlayFormat.u.raw_audio.format & 0xf)];
|
||||
int64 frames = 0;
|
||||
int64 sum = 0;
|
||||
int64 framesIndex = 0;
|
||||
int32 sumCount = 0;
|
||||
fMediaTrack->SeekToFrame(&frames);
|
||||
|
||||
TRACE("begin computing\n");
|
||||
|
||||
int32 previewIndex = 0;
|
||||
|
||||
while (fIsRendering && fMediaTrack->ReadFrames(samples, &frames) == B_OK) {
|
||||
//TRACE("reading block\n");
|
||||
framesIndex = 0;
|
||||
|
||||
while (framesIndex < frames) {
|
||||
for (; framesIndex < frames && sumCount < totalFrames/20000; framesIndex++, sumCount++) {
|
||||
sum += samples[2*framesIndex];
|
||||
sum += samples[2*framesIndex+1];
|
||||
}
|
||||
|
||||
if (previewIndex >= 20000) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (sumCount >= totalFrames/20000) {
|
||||
//TRACE("computing block %ld, sumCount %ld\n", previewIndex, sumCount);
|
||||
fPreview[previewIndex++] = (int32)(sum / 2 /(totalFrames/20000) / 32767.0 * fHeight / 2 + fHeight / 2);
|
||||
sumCount = 0;
|
||||
sum = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (fPlayFormat.u.raw_audio.format) {
|
||||
case media_raw_audio_format::B_AUDIO_FLOAT:
|
||||
ComputeRendering<float, float>();
|
||||
break;
|
||||
case media_raw_audio_format::B_AUDIO_INT:
|
||||
ComputeRendering<int32, int64>();
|
||||
break;
|
||||
case media_raw_audio_format::B_AUDIO_SHORT:
|
||||
ComputeRendering<int16, int64>();
|
||||
break;
|
||||
case media_raw_audio_format::B_AUDIO_UCHAR:
|
||||
ComputeRendering<uchar, uint32>();
|
||||
break;
|
||||
case media_raw_audio_format::B_AUDIO_CHAR:
|
||||
ComputeRendering<char, int32>();
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE("finished computing, rendering\n");
|
||||
|
||||
/* rendering */
|
||||
@@ -223,7 +255,7 @@ ScopeView::RenderTrack(BMediaTrack *track, media_format format)
|
||||
{
|
||||
fMediaTrack = track;
|
||||
fPlayFormat = format;
|
||||
release_sem(fRenderSem);
|
||||
release_sem(fRenderSem);
|
||||
}
|
||||
|
||||
|
||||
@@ -304,7 +336,8 @@ ScopeView::InitBitmap()
|
||||
|
||||
rect.OffsetToSelf(B_ORIGIN);
|
||||
rect.right -= 2;
|
||||
fBitmapView = new BView(rect.OffsetToSelf(B_ORIGIN), "bitmapView", B_FOLLOW_LEFT|B_FOLLOW_TOP, B_WILL_DRAW);
|
||||
fBitmapView = new BView(rect.OffsetToSelf(B_ORIGIN), "bitmapView",
|
||||
B_FOLLOW_LEFT|B_FOLLOW_TOP, B_WILL_DRAW);
|
||||
fBitmap->AddChild(fBitmapView);
|
||||
}
|
||||
|
||||
@@ -322,11 +355,14 @@ ScopeView::RenderBitmap()
|
||||
|
||||
fBitmapView->SetDrawingMode(B_OP_ADD);
|
||||
fBitmapView->SetHighColor(15,60,15);
|
||||
int32 leftIndex = (fTotalTime != 0) ? fLeftTime * 20000 / fTotalTime : 0;
|
||||
int32 rightIndex = (fTotalTime != 0) ? fRightTime * 20000 / fTotalTime : 20000;
|
||||
int32 leftIndex =
|
||||
(fTotalTime != 0) ? fLeftTime * 20000 / fTotalTime : 0;
|
||||
int32 rightIndex =
|
||||
(fTotalTime != 0) ? fRightTime * 20000 / fTotalTime : 20000;
|
||||
|
||||
for (int32 i = leftIndex; i<rightIndex; i++) {
|
||||
BPoint point((i - leftIndex) * width / (rightIndex - leftIndex), fPreview[i]);
|
||||
BPoint point((i - leftIndex) * width / (rightIndex - leftIndex),
|
||||
fPreview[i]);
|
||||
//TRACE("point x %f y %f\n", point.x, point.y);
|
||||
fBitmapView->StrokeLine(point, point);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ private:
|
||||
void Quit();
|
||||
static int32 RenderLaunch(void *data);
|
||||
void RenderLoop();
|
||||
template<typename T, typename U> void ComputeRendering();
|
||||
void RenderBitmap();
|
||||
void InitBitmap();
|
||||
|
||||
@@ -45,7 +46,6 @@ private:
|
||||
BMediaTrack *fMediaTrack;
|
||||
media_format fPlayFormat;
|
||||
|
||||
bool fQuitting;
|
||||
bigtime_t fMainTime;
|
||||
bigtime_t fRightTime;
|
||||
bigtime_t fLeftTime;
|
||||
|
||||
@@ -46,13 +46,13 @@ TrackSlider::AttachedToWindow()
|
||||
{
|
||||
BControl::AttachedToWindow();
|
||||
SetViewColor(B_TRANSPARENT_COLOR);
|
||||
InitBitmap();
|
||||
RenderBitmap();
|
||||
_InitBitmap();
|
||||
_RenderBitmap();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackSlider::InitBitmap()
|
||||
TrackSlider::_InitBitmap()
|
||||
{
|
||||
if (fBitmapView) {
|
||||
fBitmap->RemoveChild(fBitmapView);
|
||||
@@ -83,7 +83,7 @@ TrackSlider::InitBitmap()
|
||||
#define SLIDER_BASE 10
|
||||
|
||||
void
|
||||
TrackSlider::RenderBitmap()
|
||||
TrackSlider::_RenderBitmap()
|
||||
{
|
||||
/* rendering */
|
||||
if (fBitmap->Lock()) {
|
||||
@@ -98,20 +98,20 @@ TrackSlider::Draw(BRect updateRect)
|
||||
{
|
||||
DrawBitmapAsync(fBitmap, BPoint(0,0));
|
||||
|
||||
DrawCounter(fMainTime, fBitmapView->fPositionX, fMainTracking);
|
||||
_DrawCounter(fMainTime, fBitmapView->fPositionX, fMainTracking);
|
||||
if (fLeftTracking)
|
||||
DrawCounter(fLeftTime, fBitmapView->fLeftX, fLeftTracking);
|
||||
_DrawCounter(fLeftTime, fBitmapView->fLeftX, fLeftTracking);
|
||||
else if (fRightTracking)
|
||||
DrawCounter(fRightTime, fBitmapView->fRightX, fRightTracking);
|
||||
_DrawCounter(fRightTime, fBitmapView->fRightX, fRightTracking);
|
||||
|
||||
DrawMarker(fBitmapView->fPositionX);
|
||||
_DrawMarker(fBitmapView->fPositionX);
|
||||
|
||||
Sync();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackSlider::DrawCounter(bigtime_t timestamp, float position, bool isTracking)
|
||||
TrackSlider::_DrawCounter(bigtime_t timestamp, float position, bool isTracking)
|
||||
{
|
||||
// timecounter
|
||||
|
||||
@@ -121,7 +121,7 @@ TrackSlider::DrawCounter(bigtime_t timestamp, float position, bool isTracking)
|
||||
rgb_color white = {255,255,255};
|
||||
|
||||
char string[12];
|
||||
TimeToString(timestamp, string);
|
||||
_TimeToString(timestamp, string);
|
||||
int32 halfwidth = ((int32)fFont.StringWidth(string)) / 2;
|
||||
|
||||
float counterX = position;
|
||||
@@ -161,7 +161,7 @@ TrackSlider::DrawCounter(bigtime_t timestamp, float position, bool isTracking)
|
||||
|
||||
|
||||
void
|
||||
TrackSlider::DrawMarker(float position)
|
||||
TrackSlider::_DrawMarker(float position)
|
||||
{
|
||||
rgb_color black = {0,0,0};
|
||||
rgb_color rose = {255,152,152};
|
||||
@@ -221,7 +221,7 @@ TrackSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
|
||||
SetTracking(false);
|
||||
}
|
||||
|
||||
UpdatePosition(point);
|
||||
_UpdatePosition(point);
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ TrackSlider::MouseDown(BPoint point)
|
||||
if (!Bounds().InsetBySelf(2,2).Contains(point))
|
||||
return;
|
||||
|
||||
UpdatePosition(point);
|
||||
_UpdatePosition(point);
|
||||
SetTracking(true);
|
||||
SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);
|
||||
}
|
||||
@@ -243,7 +243,7 @@ TrackSlider::MouseUp(BPoint point)
|
||||
if (!IsTracking())
|
||||
return;
|
||||
if (Bounds().InsetBySelf(2,2).Contains(point)) {
|
||||
UpdatePosition(point);
|
||||
_UpdatePosition(point);
|
||||
}
|
||||
|
||||
fLeftTracking = fRightTracking = fMainTracking = false;
|
||||
@@ -256,7 +256,7 @@ TrackSlider::MouseUp(BPoint point)
|
||||
|
||||
|
||||
void
|
||||
TrackSlider::UpdatePosition(BPoint point)
|
||||
TrackSlider::_UpdatePosition(BPoint point)
|
||||
{
|
||||
BRect leftRect(fBitmapView->fLeftX-9, SLIDER_BASE+3, fBitmapView->fLeftX, SLIDER_BASE+16);
|
||||
BRect rightRect(fBitmapView->fRightX, SLIDER_BASE+3, fBitmapView->fRightX+9, SLIDER_BASE+16);
|
||||
@@ -283,7 +283,7 @@ TrackSlider::UpdatePosition(BPoint point)
|
||||
}
|
||||
|
||||
Invoke(&msg);
|
||||
RenderBitmap();
|
||||
_RenderBitmap();
|
||||
|
||||
//printf("fLeftPos : %Ld\n", fLeftTime);
|
||||
} else if (!fMainTracking && (fRightTracking || ((point.x > fBitmapView->fPositionX+4) && rightRect.Contains(point)))) {
|
||||
@@ -308,7 +308,7 @@ TrackSlider::UpdatePosition(BPoint point)
|
||||
}
|
||||
|
||||
Invoke(&msg);
|
||||
RenderBitmap();
|
||||
_RenderBitmap();
|
||||
|
||||
//printf("fRightPos : %Ld\n", fRightTime);
|
||||
} else {
|
||||
@@ -323,12 +323,12 @@ TrackSlider::UpdatePosition(BPoint point)
|
||||
fBitmapView->fRightX = fBitmapView->fPositionX;
|
||||
fRightTime = fMainTime;
|
||||
msg.AddInt64("right", fRightTime);
|
||||
RenderBitmap();
|
||||
_RenderBitmap();
|
||||
} else if (fBitmapView->fLeftX > fBitmapView->fPositionX) {
|
||||
fBitmapView->fLeftX = fBitmapView->fPositionX - 1;
|
||||
fLeftTime = fMainTime;
|
||||
msg.AddInt64("left", fLeftTime);
|
||||
RenderBitmap();
|
||||
_RenderBitmap();
|
||||
}
|
||||
|
||||
Invoke(&msg);
|
||||
@@ -340,7 +340,7 @@ TrackSlider::UpdatePosition(BPoint point)
|
||||
|
||||
|
||||
void
|
||||
TrackSlider::TimeToString(bigtime_t timestamp, char *string)
|
||||
TrackSlider::_TimeToString(bigtime_t timestamp, char *string)
|
||||
{
|
||||
uint32 hours = timestamp / 3600000000LL;
|
||||
timestamp -= hours * 3600000000LL;
|
||||
@@ -364,7 +364,7 @@ TrackSlider::SetMainTime(bigtime_t timestamp, bool reset)
|
||||
fLeftTime = 0;
|
||||
fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
|
||||
fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
|
||||
RenderBitmap();
|
||||
_RenderBitmap();
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
@@ -381,7 +381,7 @@ TrackSlider::SetTotalTime(bigtime_t timestamp, bool reset)
|
||||
fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
|
||||
fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
|
||||
fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
|
||||
RenderBitmap();
|
||||
_RenderBitmap();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
@@ -400,10 +400,10 @@ TrackSlider::FrameResized(float width, float height)
|
||||
{
|
||||
fBitmapView->fRight = Bounds().right - kLeftRightTrackSliderWidth;
|
||||
fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
|
||||
InitBitmap();
|
||||
_InitBitmap();
|
||||
fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
|
||||
fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
|
||||
RenderBitmap();
|
||||
_RenderBitmap();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
@@ -46,12 +46,12 @@ public:
|
||||
void ResetMainTime();
|
||||
virtual void FrameResized(float width, float height);
|
||||
private:
|
||||
void DrawCounter(bigtime_t timestamp, float position, bool isTracking);
|
||||
void DrawMarker(float position);
|
||||
void TimeToString(bigtime_t timestamp, char *string);
|
||||
void UpdatePosition(BPoint point);
|
||||
void InitBitmap();
|
||||
void RenderBitmap();
|
||||
void _DrawCounter(bigtime_t timestamp, float position, bool isTracking);
|
||||
void _DrawMarker(float position);
|
||||
void _TimeToString(bigtime_t timestamp, char *string);
|
||||
void _UpdatePosition(BPoint point);
|
||||
void _InitBitmap();
|
||||
void _RenderBitmap();
|
||||
|
||||
|
||||
bigtime_t fLeftTime;
|
||||
|
||||
@@ -2,13 +2,17 @@
|
||||
* Copyright 2005, Jérôme Duval. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers)
|
||||
* Inspired by SoundCapture from Be newsletter (Media Kit Basics:
|
||||
* Consumers and Producers)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <MediaDefs.h>
|
||||
#include <Screen.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include "DrawingTidbits.h"
|
||||
#include "VUView.h"
|
||||
|
||||
@@ -26,21 +30,22 @@ VUView::VUView(BRect rect, uint32 resizeFlags)
|
||||
fLevelCount = int(rect.Height()) / 2;
|
||||
fChannels = 2;
|
||||
fCurrentLevels = new int32[fChannels];
|
||||
for (int channel=0; channel < fChannels; channel++)
|
||||
for (int channel = 0; channel < fChannels; channel++)
|
||||
fCurrentLevels[channel] = 0;
|
||||
fBitmap = new BBitmap(rect, BScreen().ColorSpace(), true);
|
||||
|
||||
|
||||
memset(fBitmap->Bits(), 0, fBitmap->BitsLength());
|
||||
|
||||
fBitmapView = new BView(rect, "bitmapView", B_FOLLOW_LEFT|B_FOLLOW_TOP, B_WILL_DRAW);
|
||||
fBitmapView = new BView(rect, "bitmapView", B_FOLLOW_LEFT|B_FOLLOW_TOP,
|
||||
B_WILL_DRAW);
|
||||
fBitmap->AddChild(fBitmapView);
|
||||
}
|
||||
|
||||
|
||||
VUView::~VUView()
|
||||
{
|
||||
|
||||
delete fBitmap;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,14 +53,14 @@ void
|
||||
VUView::AttachedToWindow()
|
||||
{
|
||||
SetViewColor(B_TRANSPARENT_COLOR);
|
||||
Run();
|
||||
_Run();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VUView::DetachedFromWindow()
|
||||
{
|
||||
Quit();
|
||||
_Quit();
|
||||
}
|
||||
|
||||
|
||||
@@ -69,16 +74,16 @@ VUView::Draw(BRect updateRect)
|
||||
|
||||
|
||||
void
|
||||
VUView::Run()
|
||||
VUView::_Run()
|
||||
{
|
||||
fThreadId = spawn_thread(&RenderLaunch, "VU view", B_NORMAL_PRIORITY, this);
|
||||
fThreadId = spawn_thread(_RenderLaunch, "VU view", B_NORMAL_PRIORITY, this);
|
||||
if (fThreadId < 0)
|
||||
return;
|
||||
resume_thread(fThreadId);
|
||||
}
|
||||
|
||||
void
|
||||
VUView::Quit()
|
||||
VUView::_Quit()
|
||||
{
|
||||
fQuitting = true;
|
||||
snooze(10000);
|
||||
@@ -88,18 +93,19 @@ VUView::Quit()
|
||||
|
||||
|
||||
int32
|
||||
VUView::RenderLaunch(void *data)
|
||||
VUView::_RenderLaunch(void *data)
|
||||
{
|
||||
VUView *vu = (VUView*) data;
|
||||
vu->RenderLoop();
|
||||
vu->_RenderLoop();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
#define SHIFT_UNTIL(value,shift,min) value = (value - shift > min) ? (value - shift) : min
|
||||
#define SHIFT_UNTIL(value,shift,min) \
|
||||
value = (value - shift > min) ? (value - shift) : min
|
||||
|
||||
void
|
||||
VUView::RenderLoop()
|
||||
VUView::_RenderLoop()
|
||||
{
|
||||
rgb_color levels[fLevelCount][2];
|
||||
|
||||
@@ -167,29 +173,72 @@ VUView::RenderLoop()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VUView::ComputeNextLevel(void *data, size_t size)
|
||||
template<typename T>
|
||||
T
|
||||
VUView::_ComputeNextLevel(void *data, size_t size, uint32 format, int32 channel)
|
||||
{
|
||||
int16* samp = (int16*)data;
|
||||
T* samp = (T*)data;
|
||||
|
||||
// get the min and max values in the nibbling interval
|
||||
// and set max to be the greater of the absolute value
|
||||
// of these.
|
||||
|
||||
T min = 0, max = 0;
|
||||
for (uint32 i = channel; i < size/sizeof(T); i += fChannels) {
|
||||
if (min > samp[i])
|
||||
min = samp[i];
|
||||
else if (max < samp[i])
|
||||
max = samp[i];
|
||||
}
|
||||
if (-max > (min + 1))
|
||||
max = -min;
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VUView::ComputeLevels(void* data, size_t size, uint32 format)
|
||||
{
|
||||
for (int32 channel = 0; channel < fChannels; channel++) {
|
||||
|
||||
// get the min and max values in the nibbling interval
|
||||
// and set max to be the greater of the absolute value
|
||||
// of these.
|
||||
|
||||
int mi = 0, ma = 0;
|
||||
for (uint32 ix=channel; ix<size/sizeof(uint16); ix += fChannels) {
|
||||
if (mi > samp[ix]) mi = samp[ix];
|
||||
else if (ma < samp[ix]) ma = samp[ix];
|
||||
switch (format) {
|
||||
case media_raw_audio_format::B_AUDIO_FLOAT:
|
||||
{
|
||||
float max = _ComputeNextLevel<float>(data, size, format,
|
||||
channel);
|
||||
fCurrentLevels[channel] = (uint8)(max * 127);
|
||||
break;
|
||||
}
|
||||
case media_raw_audio_format::B_AUDIO_INT:
|
||||
{
|
||||
int32 max = _ComputeNextLevel<int32>(data, size, format,
|
||||
channel);
|
||||
fCurrentLevels[channel] = max / (2 << (32-8));
|
||||
break;
|
||||
}
|
||||
case media_raw_audio_format::B_AUDIO_SHORT:
|
||||
{
|
||||
int16 max = _ComputeNextLevel<int16>(data, size, format,
|
||||
channel);
|
||||
fCurrentLevels[channel] = max / (2 << (16-7));
|
||||
break;
|
||||
}
|
||||
case media_raw_audio_format::B_AUDIO_UCHAR:
|
||||
{
|
||||
uchar max = _ComputeNextLevel<uchar>(data, size, format,
|
||||
channel);
|
||||
fCurrentLevels[channel] = max / 2 - 127;
|
||||
break;
|
||||
}
|
||||
case media_raw_audio_format::B_AUDIO_CHAR:
|
||||
{
|
||||
char max = _ComputeNextLevel<char>(data, size, format,
|
||||
channel);
|
||||
fCurrentLevels[channel] = max / 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (-ma > mi) ma = (mi == -32768) ? 32767 : -mi;
|
||||
|
||||
uint8 n = ma / (2 << (16-7));
|
||||
|
||||
fCurrentLevels[channel] = n;
|
||||
if (fCurrentLevels[channel] < 0)
|
||||
fCurrentLevels[channel] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
* Copyright 2005, Jérôme Duval. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers)
|
||||
* Inspired by SoundCapture from Be newsletter (Media Kit Basics:
|
||||
* Consumers and Producers)
|
||||
*/
|
||||
|
||||
#ifndef VUVIEW_H
|
||||
@@ -20,13 +21,15 @@ public:
|
||||
void AttachedToWindow();
|
||||
void DetachedFromWindow();
|
||||
void Draw(BRect updateRect);
|
||||
void ComputeNextLevel(void *data, size_t size);
|
||||
|
||||
void ComputeLevels(void* data, size_t size, uint32 format);
|
||||
|
||||
private:
|
||||
void Run();
|
||||
void Quit();
|
||||
static int32 RenderLaunch(void *data);
|
||||
void RenderLoop();
|
||||
void _Run();
|
||||
void _Quit();
|
||||
static int32 _RenderLaunch(void *data);
|
||||
void _RenderLoop();
|
||||
template<typename T> T _ComputeNextLevel(void *data,
|
||||
size_t size, uint32 format, int32 channel);
|
||||
|
||||
thread_id fThreadId;
|
||||
BBitmap *fBitmap;
|
||||
|
||||
@@ -99,7 +99,7 @@ VolumeSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
|
||||
if (!fSoundPlayer || !Bounds().InsetBySelf(2,2).Contains(point))
|
||||
return;
|
||||
|
||||
UpdateVolume(point);
|
||||
_UpdateVolume(point);
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ VolumeSlider::MouseDown(BPoint point)
|
||||
if (!fSoundPlayer || !Bounds().InsetBySelf(2,2).Contains(point))
|
||||
return;
|
||||
|
||||
UpdateVolume(point);
|
||||
_UpdateVolume(point);
|
||||
SetTracking(true);
|
||||
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
|
||||
}
|
||||
@@ -121,7 +121,7 @@ VolumeSlider::MouseUp(BPoint point)
|
||||
if (!IsTracking())
|
||||
return;
|
||||
if (fSoundPlayer && Bounds().InsetBySelf(2,2).Contains(point)) {
|
||||
UpdateVolume(point);
|
||||
_UpdateVolume(point);
|
||||
}
|
||||
|
||||
Invoke();
|
||||
@@ -132,7 +132,7 @@ VolumeSlider::MouseUp(BPoint point)
|
||||
|
||||
|
||||
void
|
||||
VolumeSlider::UpdateVolume(BPoint point)
|
||||
VolumeSlider::_UpdateVolume(BPoint point)
|
||||
{
|
||||
fVolume = MIN(MAX(point.x, 11), fRight);
|
||||
fVolume = (fVolume - 11) / (fRight - 11);
|
||||
|
||||
@@ -23,7 +23,8 @@ public:
|
||||
virtual void MouseDown(BPoint point);
|
||||
void SetSoundPlayer(BSoundPlayer *player);
|
||||
private:
|
||||
void UpdateVolume(BPoint point);
|
||||
void _UpdateVolume(BPoint point);
|
||||
|
||||
BBitmap fLeftBitmap, fRightBitmap, fButtonBitmap;
|
||||
float fRight;
|
||||
float fVolume;
|
||||
|
||||
Reference in New Issue
Block a user