- Added version number.

- Added the Live Input menu, although it doesn't do anything yet.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8159 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
mahlzeit
2004-06-25 12:16:48 +00:00
parent 9310e248b4
commit f124b49e87
5 changed files with 149 additions and 21 deletions
+1
View File
@@ -13,4 +13,5 @@ App MidiPlayer :
LinkSharedOSLibs MidiPlayer :
be
midi
midi2
;
+1 -1
View File
@@ -47,7 +47,7 @@ void MidiPlayerApp::AboutRequested()
{
(new BAlert(
NULL,
"Haiku MIDI Player\n\n"
"Haiku MIDI Player 1.0.0 beta\n\n"
"This tiny program\n"
"Knows how to play thousands of\n"
"Cheesy sounding songs",
+120 -15
View File
@@ -20,6 +20,7 @@
* DEALINGS IN THE SOFTWARE.
*/
#include <MidiRoster.h>
#include <StorageKit.h>
#include "MidiPlayerApp.h"
@@ -42,6 +43,7 @@ MidiPlayerWindow::MidiPlayerWindow()
windowX = -1;
windowY = -1;
threadId = -1;
inputId = -1;
be_synth->SetSamplingRate(44100);
@@ -86,6 +88,10 @@ void MidiPlayerWindow::MessageReceived(BMessage* msg)
case MSG_SHOW_SCOPE:
OnShowScope();
break;
case MSG_INPUT_CHANGED:
OnInputChanged(msg);
break;
case MSG_REVERB_NONE:
OnReverb(B_REVERB_NONE);
@@ -137,9 +143,77 @@ void MidiPlayerWindow::FrameMoved(BPoint origin)
//------------------------------------------------------------------------------
void MidiPlayerWindow::MenusBeginning()
{
for (int32 t = inputPopUp->CountItems() - 1; t > 0; --t)
{
delete inputPopUp->RemoveItem(t);
}
bool seenInput = false;
if (inputId == -1)
{
inputOff->SetMarked(true);
seenInput = true;
}
int32 id = 0;
BMidiEndpoint* endp;
while ((endp = BMidiRoster::NextEndpoint(&id)) != NULL)
{
if (endp->IsProducer())
{
BMessage* msg = new BMessage;
msg->what = MSG_INPUT_CHANGED;
msg->AddInt32("id", id);
BMenuItem* item = new BMenuItem(endp->Name(), msg);
inputPopUp->AddItem(item);
if (inputId == id)
{
item->SetMarked(true);
seenInput = true;
}
}
endp->Release();
}
if (!seenInput) // endpoint no longer exists
{
inputOff->SetMarked(true);
}
}
//------------------------------------------------------------------------------
void MidiPlayerWindow::CreateInputMenu()
{
inputPopUp = new BPopUpMenu("inputPopUp");
BMessage* msg = new BMessage;
msg->what = MSG_INPUT_CHANGED;
msg->AddInt32("id", -1);
inputOff = new BMenuItem("Off", msg);
inputPopUp->AddItem(inputOff);
inputMenu = new BMenuField(
BRect(0, 0, 128, 17), "inputMenu", "Live Input:", inputPopUp,
B_FOLLOW_LEFT | B_FOLLOW_TOP);
inputMenu->SetDivider(55);
inputMenu->ResizeToPreferred();
}
//------------------------------------------------------------------------------
void MidiPlayerWindow::CreateReverbMenu()
{
BPopUpMenu* menu = new BPopUpMenu("reverbPopUp");
BPopUpMenu* reverbPopUp = new BPopUpMenu("reverbPopUp");
reverbNone = new BMenuItem(
"None", new BMessage(MSG_REVERB_NONE));
@@ -159,18 +233,18 @@ void MidiPlayerWindow::CreateReverbMenu()
reverbDungeon = new BMenuItem(
"Dungeon", new BMessage(MSG_REVERB_DUNGEON));
menu->AddItem(reverbNone);
menu->AddItem(reverbCloset);
menu->AddItem(reverbGarage);
menu->AddItem(reverbIgor);
menu->AddItem(reverbCavern);
menu->AddItem(reverbDungeon);
reverbPopUp->AddItem(reverbNone);
reverbPopUp->AddItem(reverbCloset);
reverbPopUp->AddItem(reverbGarage);
reverbPopUp->AddItem(reverbIgor);
reverbPopUp->AddItem(reverbCavern);
reverbPopUp->AddItem(reverbDungeon);
reverbMenu = new BMenuField(
BRect(0, 0, 128, 17), "reverbMenu", "Reverb:", menu,
BRect(0, 0, 128, 17), "reverbMenu", "Reverb:", reverbPopUp,
B_FOLLOW_LEFT | B_FOLLOW_TOP);
reverbMenu->SetDivider(50);
reverbMenu->SetDivider(55);
reverbMenu->ResizeToPreferred();
}
@@ -187,6 +261,7 @@ void MidiPlayerWindow::CreateViews()
showScope->SetValue(B_CONTROL_ON);
showScope->ResizeToPreferred();
CreateInputMenu();
CreateReverbMenu();
volumeSlider = new BSlider(
@@ -197,7 +272,7 @@ void MidiPlayerWindow::CreateViews()
volumeSlider->UseFillColor(true, &col);
volumeSlider->SetModificationMessage(new BMessage(MSG_VOLUME));
volumeSlider->ResizeToPreferred();
volumeSlider->ResizeTo(_W(scopeView) - 37, _H(volumeSlider));
volumeSlider->ResizeTo(_W(scopeView) - 42, _H(volumeSlider));
playButton = new BButton(
BRect(0, 1, 80, 1), "playButton", "Play", new BMessage(MSG_PLAY_STOP),
@@ -226,13 +301,14 @@ void MidiPlayerWindow::CreateViews()
float width = 8 + _W(scopeView) + 8;
float height =
+ 8 + _H(scopeView)
8 + _H(scopeView)
+ 8 + _H(showScope)
+ 4 + _H(reverbMenu)
+ 4 + _H(inputMenu)
+ _H(reverbMenu)
+ 2 + _H(volumeSlider)
+ 10 + _H(divider)
+ 6 + _H(playButton)
+ 10;
+ 16;
ResizeTo(width, height);
@@ -241,6 +317,7 @@ void MidiPlayerWindow::CreateViews()
background->AddChild(scopeView);
background->AddChild(showScope);
background->AddChild(reverbMenu);
background->AddChild(inputMenu);
background->AddChild(volumeLabel);
background->AddChild(volumeSlider);
background->AddChild(divider);
@@ -250,14 +327,17 @@ void MidiPlayerWindow::CreateViews()
scopeView->MoveTo(8, y);
y += _H(scopeView) + 8;
showScope->MoveTo(8 + 50, y);
showScope->MoveTo(8 + 55, y);
y += _H(showScope) + 4;
inputMenu->MoveTo(8, y);
y += _H(inputMenu);
reverbMenu->MoveTo(8, y);
y += _H(reverbMenu) + 2;
volumeLabel->MoveTo(8, y);
volumeSlider->MoveTo(8 + 44, y);
volumeSlider->MoveTo(8 + 49, y);
y += _H(volumeSlider) + 10;
divider->MoveTo(8, y);
@@ -287,6 +367,8 @@ void MidiPlayerWindow::InitControls()
showScope->SetValue(scopeEnabled ? B_CONTROL_ON : B_CONTROL_OFF);
scopeView->SetEnabled(scopeEnabled);
inputOff->SetMarked(true);
reverbNone->SetMarked(reverb == B_REVERB_NONE);
reverbCloset->SetMarked(reverb == B_REVERB_CLOSET);
reverbGarage->SetMarked(reverb == B_REVERB_GARAGE);
@@ -486,6 +568,29 @@ void MidiPlayerWindow::OnShowScope()
//------------------------------------------------------------------------------
void MidiPlayerWindow::OnInputChanged(BMessage* msg)
{
int32 newId;
if (msg->FindInt32("id", &newId) == B_OK)
{
inputId = newId;
// if (!instrLoaded)
// be_synth->LoadInstruments(all)
// if id != -1
// if playing -> Stop() // AARGH, need thread!
// connect SynthBridge (from MidiUtil) to producer endpoint
// else if SynthBridge still connected
// disconnect SynthBridge
// NOTE: we should also disconnect SynthBridge when launching
// a MIDI file!!! (successfull or not)
}
}
//------------------------------------------------------------------------------
void MidiPlayerWindow::OnReverb(reverb_mode mode)
{
reverb = mode;
+8
View File
@@ -32,6 +32,7 @@ enum
{
MSG_PLAY_STOP = 1000,
MSG_SHOW_SCOPE,
MSG_INPUT_CHANGED,
MSG_REVERB_NONE,
MSG_REVERB_CLOSET,
MSG_REVERB_GARAGE,
@@ -53,11 +54,13 @@ public:
virtual bool QuitRequested();
virtual void MessageReceived(BMessage* msg);
virtual void FrameMoved(BPoint origin);
virtual void MenusBeginning();
private:
typedef BWindow super;
void CreateInputMenu();
void CreateReverbMenu();
void CreateViews();
void CenterOnScreen();
@@ -76,12 +79,16 @@ private:
void OnPlayStop();
void OnShowScope();
void OnInputChanged(BMessage* msg);
void OnReverb(reverb_mode mode);
void OnVolume();
void OnDrop(BMessage* msg);
ScopeView* scopeView;
BCheckBox* showScope;
BMenuField* inputMenu;
BPopUpMenu* inputPopUp;
BMenuItem* inputOff;
BMenuField* reverbMenu;
BMenuItem* reverbNone;
BMenuItem* reverbCloset;
@@ -101,6 +108,7 @@ private:
BMidiSynthFile synth;
entry_ref ref;
thread_id threadId;
int32 inputId;
};
#endif // MIDI_PLAYER_WINDOW_H
+19 -5
View File
@@ -4,23 +4,37 @@
</head>
<body>
<h1>Haiku MIDI Player</h1>
<h1>Haiku MIDI Player 1.0.0 beta</h1>
<p>This is a simple application to play MIDI songs.</p>
<p>Differences with the BeOS R5 MidiPlayer:</p>
<p>To play a MIDI song, you can:</p>
<ul>
<li>double-click it, or</li>
<li>drag it on the MidiPlayer icon, or</li>
<li>drag it into the MidiPlayer window, or</li>
<li>type "MidiPlayer song.mid" in Terminal.</li>
</ul>
<p>Hopefully, most of the options will be obvious, although Live Input may require a few lines of explanation.</p>
<p>The <b>Live Input</b> feature enables you to attach other applications to the Haiku software synthesizer, for example a virtual MIDI keyboard. MidiPlayer looks at the MIDI roster for compatible producer endpoints. If none are found, Live Input is not available.</p>
<h3>Differences with the BeOS R5 MidiPlayer:</h3>
<ul>
<li>User interface looks slightly different (better?)</li>
<li>Play and Stop are now one and the same button.</li>
<li>There is no Open File... button. You open MIDI songs by dragging them into the window.</li>
<li>There is no Live Input feature.</li>
<li>There is no Open File... function.</li>
<li>You cannot set the Quality of the sound (always 44100 Hz).</li>
</ul>
<p>If people really <i>really</i> want these missing features, then feel free to add them :-)</p>
<p>Note: The code can be a little tricky at times, since it uses fire-and-forget threads to load new songs and to stop playback. The reason for this is the scope: we want to keep repainting the scope view even when fading out a song (because this looks cool), but fading blocks the calling thread. If we were to block the window's looper, then the scope wouldn't repaint during the fade-out. So we fade using a separate thread instead. Unfortunately, this makes the code much less clean as it introduces several race conditions. Yech. See the source for more details.</p>
<h3>Implementation notes</h3>
<p>The code can be a little tricky at times, since it uses fire-and-forget threads to load new songs and to stop playback. The reason for this is the scope: we want to keep repainting the ScopeView even when fading out a song (because this looks cool), but fading blocks the calling thread. If we were to block the window's looper, then the scope wouldn't repaint during the fade-out. So we fade using a separate thread instead. Unfortunately, this makes the code much less clean as it introduces several race conditions. Yech. See the source for more details.</p>
</body>
</html>