1/* 2Author: Jerome LEVEQUE 3Email: jerl1@caramail.com 4*/ 5#include "MidiPlayerWindow.h" 6#include "MidiDelay.h" 7#include "Activity.h" 8 9#include <Application.h> 10#include <Roster.h> 11#include <Resources.h> 12#include <Alert.h> 13#include <PopUpMenu.h> 14#include <MenuItem.h> 15#include <StringView.h> 16#include <String.h> 17#include <File.h> 18#include <MidiStore.h> 19#include <MidiPort.h> 20#include <MidiSynth.h> 21#include <MidiSynthFile.h> 22 23//---------------------------------------------------------- 24 25class MidiPlayerApp : public BApplication 26{ 27public: 28 MidiPlayerApp(void) 29 : BApplication("application/x-vnd.MidiPlayer") 30 { 31 app_info info; 32 BFile file; 33 BResources resource; 34 size_t len; 35 GetAppInfo(&info); 36 if (file.SetTo(&(info.ref), B_READ_ONLY) != B_OK) return; 37 resource.SetTo(&file); 38 BPoint *origin((BPoint*)resource.LoadResource('BPNT', "origin", &len)); 39 if (origin == NULL) 40 fWindows = new MidiPlayerWindow(BPoint(100.0, 100.0)); 41 else 42 fWindows = new MidiPlayerWindow(*origin); 43 } 44 45//-------------- 46 47 void ReadyToRun(void) 48 { 49 fWindows->Show(); 50 } 51 52//-------------- 53 54 void SetOrigin(BPoint origin) 55 { 56 app_info info; 57 BFile file; 58 BResources resource; 59 int32 temp; 60 GetAppInfo(&info); 61 if (file.SetTo(&(info.ref), B_READ_WRITE) != B_OK) return; 62 resource.SetTo(&file); 63 temp = resource.RemoveResource('BPNT', 1); 64 temp = resource.AddResource('BPNT', 1, &origin, sizeof(origin), "origin"); 65 } 66 67//-------------- 68 69 virtual void RefsReceived(BMessage *message) 70 { 71 message->what = B_SIMPLE_DATA; 72 fWindows->PostMessage(message); 73 } 74 75//-------------- 76//-------------- 77//-------------- 78//-------------- 79//-------------- 80 81private: 82 MidiPlayerWindow *fWindows; 83 84//-------------- 85 86}; 87 88//---------------------------------------------------------- 89//---------------------------------------------------------- 90//---------------------------------------------------------- 91//---------------------------------------------------------- 92//---------------------------------------------------------- 93//---------------------------------------------------------- 94//---------------------------------------------------------- 95//---------------------------------------------------------- 96 97MidiPlayerWindow::MidiPlayerWindow(BPoint start) 98 : BWindow(BRect(start, start + BPoint(660, 360)), "Midi Player", 99 B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE), 100 fMidiInput(NULL), 101 fMidiOutput(NULL), 102 fMidiDisplay(NULL), 103 fInputType(0), 104 fOutputType(0), 105 fDisplayType(0), 106 fInputFilePanel(NULL), 107 fOutputFilePanel(NULL), 108 fInputCurrentEvent(0), 109 fOutputCurrentEvent(0) 110{ 111 AddChild(fStandartView = new MidiPlayerView()); 112 fMidiDelay = new MidiDelay(); 113} 114 115//---------------------------------------------------------- 116 117MidiPlayerWindow::~MidiPlayerWindow(void) 118{ 119 Disconnect(); 120 delete fMidiInput; 121 delete fMidiOutput; 122} 123 124//---------------------------------------------------------- 125 126bool MidiPlayerWindow::QuitRequested(void) 127{ 128 be_app->PostMessage(B_QUIT_REQUESTED); 129 return true; 130} 131 132//---------------------------------------------------------- 133 134void MidiPlayerWindow::FrameMoved(BPoint origin) 135{ 136 ((MidiPlayerApp*)be_app)->SetOrigin(origin); 137} 138 139//---------------------------------------------------------- 140 141void MidiPlayerWindow::MessageReceived(BMessage *msg) 142{ 143uint32 temp = 0; 144BPopUpMenu *MidiPortMenu = NULL; 145BMenuItem *item = NULL; 146BMessage message; 147entry_ref ref; 148 switch (msg->what) 149 { 150//-------------- 151//For The Input 152//-------------- 153//-------------- 154 case INPUT_CHANGE_TO_FILE : 155 if (fInputType == FILE) 156 break; 157 fInputType = FILE; 158 Disconnect(); 159 delete fMidiInput; 160 fMidiInput = new BMidiStore(); 161 if (!fMidiInput) 162 { 163 (new BAlert(NULL, "Can't initialise a BMidiStore object", "OK"))->Go(); 164 break; 165 } 166 Connect(); 167 PostMessage(msg, fStandartView); 168 break; 169//-------------- 170 case INPUT_CHANGE_TO_MIDIPORT : 171 if (fInputType == MIDIPORT) 172 break; 173 fInputType = MIDIPORT; 174 Disconnect(); 175 delete fMidiInput; 176 fMidiInput = new BMidiPort(); 177 if (!fMidiInput) 178 { 179 (new BAlert(NULL, "Can't initialise a BMidiPort object", "OK"))->Go(); 180 break; 181 } 182 MidiPortMenu = new BPopUpMenu("Midi Port"); 183 for(int i = ((BMidiPort*)fMidiInput)->CountDevices(); i > 0; i--) 184 { 185 char name[B_OS_NAME_LENGTH]; 186 ((BMidiPort*)fMidiInput)->GetDeviceName(i - 1, name); 187 MidiPortMenu->AddItem(new BMenuItem(name, new BMessage(CHANGE_INPUT_MIDIPORT))); 188 } 189 msg->AddPointer("Menu", MidiPortMenu); 190 Connect(); 191 PostMessage(msg, fStandartView); 192 break; 193//-------------- 194//For the Output 195//-------------- 196//-------------- 197 case OUTPUT_CHANGE_TO_FILE : 198 if (fOutputType == FILE) 199 break; 200 fOutputType = FILE; 201 Disconnect(); 202 delete fMidiOutput; 203 fMidiOutput = new BMidiStore(); 204 if (!fMidiOutput) 205 { 206 (new BAlert(NULL, "Can't initialise a BMidiStore object", "OK"))->Go(); 207 break; 208 } 209 Connect(); 210 PostMessage(msg, fStandartView); 211 break; 212//-------------- 213 case OUTPUT_CHANGE_TO_BEOS_SYNTH : 214 if (fOutputType == BEOS_SYNTH) 215 break; 216 fOutputType = BEOS_SYNTH; 217 Disconnect(); 218 delete fMidiOutput; 219 fMidiOutput = new BMidiSynth(); 220 if (!fMidiOutput) 221 { 222 (new BAlert(NULL, "Can't initialise a BMidiSynth object", "OK"))->Go(); 223 break; 224 } 225 Connect(); 226 ((BMidiSynth*)fMidiOutput)->EnableInput(true, true); 227 PostMessage(msg, fStandartView); 228 break; 229//-------------- 230 case OUTPUT_CHANGE_TO_BEOS_SYNTH_FILE : 231 if (fOutputType == BEOS_SYNTH_FILE) 232 break; 233 fOutputType = BEOS_SYNTH_FILE; 234 Disconnect(); 235 delete fMidiOutput; 236 fMidiOutput = new BMidiSynthFile(); 237 if (!fMidiOutput) 238 { 239 (new BAlert(NULL, "Can't initialise a BMidiSynth object", "OK"))->Go(); 240 break; 241 } 242 Connect(); 243 ((BMidiSynthFile*)fMidiOutput)->EnableInput(true, true); 244 PostMessage(msg, fStandartView); 245 break; 246//-------------- 247 case OUTPUT_CHANGE_TO_MIDIPORT : 248 if (fOutputType == MIDIPORT) 249 break; 250 fOutputType = MIDIPORT; 251 Disconnect(); 252 delete fMidiOutput; 253 fMidiOutput = new BMidiPort(); 254 if (!fMidiOutput) 255 { 256 (new BAlert(NULL, "Can't initialise a BMidiPort object", "OK"))->Go(); 257 break; 258 } 259 MidiPortMenu = new BPopUpMenu("Midi Port"); 260 for(int i = ((BMidiPort*)fMidiOutput)->CountDevices(); i > 0; i--) 261 { 262 char name[B_OS_NAME_LENGTH]; 263 ((BMidiPort*)fMidiOutput)->GetDeviceName(i - 1, name); 264 MidiPortMenu->AddItem(new BMenuItem(name, new BMessage(CHANGE_OUTPUT_MIDIPORT))); 265 } 266 msg->AddPointer("Menu", MidiPortMenu); 267 Connect(); 268 PostMessage(msg, fStandartView); 269 break; 270//-------------- 271//For the display view 272//-------------- 273//-------------- 274 case VIEW_CHANGE_TO_NONE : 275 if (fDisplayType == 0) 276 break; 277 fDisplayType = 0; 278 if (fMidiDisplay != NULL) 279 fMidiDelay->Disconnect(fMidiDisplay); //Object will be deleted in MidiPlayerView::RemoveAll 280 PostMessage(msg, fStandartView); 281 break; 282//-------------- 283 case VIEW_CHANGE_TO_SCOPE : 284 if (fDisplayType == SCOPE) 285 break; 286 fDisplayType = SCOPE; 287 PostMessage(msg, fStandartView); 288 break; 289//-------------- 290 case VIEW_CHANGE_TO_ACTIVITY : 291 if (fDisplayType == ACTIVITY) 292 break; 293 fDisplayType = ACTIVITY; 294 fMidiDisplay = (BMidi*)new Activity(BRect(10, 25, 340, 340)); 295 fMidiDelay->Connect(fMidiDisplay); 296 ((Activity*)fMidiDisplay)->Start(); 297 msg->AddPointer("View", fMidiDisplay); 298 PostMessage(msg, fStandartView); 299 break; 300//-------------- 301//-------------- 302//Message from Input file 303//-------------- 304 case CHANGE_INPUT_FILE : 305 if (fInputFilePanel) 306 { 307 entry_ref File; 308 if (msg->FindRef("refs", &File) != B_OK) 309 break; 310 Disconnect(); 311 delete fMidiInput; 312 fMidiInput = new BMidiStore(); 313 if (!fMidiInput) 314 { 315 (new BAlert(NULL, "Can't initialise a BMidiPort object", "OK"))->Go(); 316 return; 317 } 318 Connect(); 319 if (((BMidiStore*)fMidiInput)->Import(&File) == B_OK) 320 { 321 BStringView *aStringView = fStandartView->GetInputStringView(); 322 aStringView->SetText(File.name); 323 } 324 delete fInputFilePanel; 325 fInputFilePanel = NULL; 326 } 327 else 328 { 329 BMessenger messenger(this) 330 fInputFilePanel = new BFilePanel(B_OPEN_PANEL, &messenger, 331 NULL, B_FILE_NODE, false, msg); 332 fInputFilePanel->Show(); 333 } 334 break; 335//-------------- 336 case REWIND_INPUT_FILE : 337 ((BMidiStore*)fMidiInput)->Stop(); 338 if (fMidiOutput) fMidiOutput->AllNotesOff(); 339 fInputCurrentEvent = 0; 340 return; 341//-------------- 342 case PLAY_INPUT_FILE : 343 ((BMidiStore*)fMidiInput)->SetCurrentEvent(fInputCurrentEvent); 344 ((BMidiStore*)fMidiInput)->Start(); 345 break; 346//-------------- 347 case PAUSE_INPUT_FILE : 348 fInputCurrentEvent = ((BMidiStore*)fMidiInput)->CurrentEvent(); 349 ((BMidiStore*)fMidiInput)->Stop(); 350 if (fMidiOutput) fMidiOutput->AllNotesOff(); 351 break; 352//-------------- 353//-------------- 354//Message from Output file 355//-------------- 356 case CHANGE_OUTPUT_FILE : 357 if (fOutputFilePanel) 358 { 359 const char *filename; 360 msg->FindRef("directory", &fOutputFile); 361 msg->FindString("name", &filename); 362 BDirectory path(&fOutputFile); 363 BFile fichier(&path, filename, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 364 if (fichier.InitCheck() == B_OK) 365 { 366 BStringView *aStringView = fStandartView->GetOutputStringView(); 367 BEntry entry(&path, filename); 368 entry.GetRef(&fOutputFile); 369 aStringView->SetText(fOutputFile.name); 370 } 371 else 372 { 373 (new BAlert(NULL, "Can't Create File", "OK"))->Go(); 374 } 375 delete fOutputFilePanel; 376 fOutputFilePanel = NULL; 377 } 378 else 379 { 380 BMessenger messenger(this) 381 fOutputFilePanel = new BFilePanel(B_SAVE_PANEL, &messenger, 382 NULL, B_FILE_NODE, false, msg); 383 fOutputFilePanel->Show(); 384 } 385 break; 386//-------------- 387 case REWIND_OUTPUT_FILE : 388 Disconnect(); 389 delete fMidiOutput; 390 fMidiOutput = new BMidiPort(); 391 if (!fMidiOutput) 392 { 393 (new BAlert(NULL, "Can't initialise a BMidiPort object", "OK"))->Go(); 394 return; 395 } 396 Connect(); 397 fOutputCurrentEvent = 0; 398 return; 399//-------------- 400 case SAVE_OUTPUT_FILE : 401 ((BMidiStore*)fMidiOutput)->Export(&fOutputFile, 0); 402 break; 403//-------------- 404//-------------- 405//Message from the input Midiport 406//-------------- 407 case CHANGE_INPUT_MIDIPORT : 408 if (msg->FindPointer("source", (void**)&item) == B_OK) 409 { 410 ((BMidiPort*)fMidiInput)->Open(item->Label()); 411 ((BMidiPort*)fMidiInput)->Start(); 412 } 413 break; 414//-------------- 415//-------------- 416//Message from the output Midiport 417//-------------- 418 case CHANGE_OUTPUT_MIDIPORT : 419 if (msg->FindPointer("source", (void**)&item) == B_OK) 420 { 421 ((BMidiPort*)fMidiOutput)->Open(item->Label()); 422 ((BMidiPort*)fMidiOutput)->Start(); 423 } 424 break; 425//-------------- 426//-------------- 427//Message from the BeOS Synth 428//-------------- 429 case CHANGE_BEOS_SYNTH_FILE: 430 if (fOutputFilePanel) 431 { 432 msg->FindRef("refs", &fOutputFile); 433 ((BMidiSynthFile*)fMidiOutput)->UnloadFile(); 434 if (((BMidiSynthFile*)fMidiOutput)->LoadFile(&fOutputFile) == B_OK) 435 { 436 BStringView *aStringView = fStandartView->GetOutputStringView(); 437 aStringView->SetText(fOutputFile.name); 438 } 439 delete fOutputFilePanel; 440 fOutputFilePanel = NULL; 441 } 442 else 443 { 444 BMessenger messenger(this) 445 fOutputFilePanel = new BFilePanel(B_OPEN_PANEL, &messenger, 446 NULL, B_FILE_NODE, false, msg); 447 fOutputFilePanel->Show(); 448 } 449 break; 450//-------------- 451 case REWIND_BEOS_SYNTH_FILE : 452 ((BMidiSynthFile*)fMidiOutput)->Stop(); 453 fOutputCurrentEvent = 0; 454 return; 455//-------------- 456 case PLAY_BEOS_SYNTH_FILE : 457 if (fOutputCurrentEvent == 1) 458 ((BMidiSynthFile*)fMidiOutput)->Resume(); 459 else 460 ((BMidiSynthFile*)fMidiOutput)->Start(); 461 fOutputCurrentEvent = 0; 462 break; 463//-------------- 464 case PAUSE_BEOS_SYNTH_FILE : 465 fOutputCurrentEvent = 1; 466 ((BMidiSynthFile*)fMidiOutput)->Pause(); 467 break; 468//-------------- 469 case CHANGE_SAMPLE_RATE_SYNTH : 470 msg->FindInt32("index", (int32*)&temp); 471 switch(temp) 472 { 473 case 0 : be_synth->SetSamplingRate(11025); break; 474 case 1 : be_synth->SetSamplingRate(22050); break; 475 case 2 : be_synth->SetSamplingRate(44100); break; 476 } 477 break; 478//-------------- 479 case CHANGE_INTERPOLATION_TYPE_SYNTH : 480 msg->FindInt32("index", (int32*)&temp); 481 switch(temp) 482 { 483 case 0 : be_synth->SetInterpolation(B_DROP_SAMPLE); break; 484 case 1 : be_synth->SetInterpolation(B_2_POINT_INTERPOLATION); break; 485 case 2 : be_synth->SetInterpolation(B_LINEAR_INTERPOLATION); break; 486 } 487 break; 488//-------------- 489 case CHANGE_REVERB_TYPE_SYNTH : 490 msg->FindInt32("index", (int32*)&temp); 491 switch(temp) 492 { 493 case 0 : 494 be_synth->EnableReverb(false); 495 break; 496 case 1 : 497 be_synth->EnableReverb(true); 498 be_synth->SetReverb(B_REVERB_CLOSET); 499 break; 500 case 2 : 501 be_synth->EnableReverb(true); 502 be_synth->SetReverb(B_REVERB_GARAGE); 503 break; 504 case 3 : 505 be_synth->EnableReverb(true); 506 be_synth->SetReverb(B_REVERB_BALLROOM); 507 break; 508 case 4 : 509 be_synth->EnableReverb(true); 510 be_synth->SetReverb(B_REVERB_CAVERN); 511 break; 512 case 5 : 513 be_synth->EnableReverb(true); 514 be_synth->SetReverb(B_REVERB_DUNGEON); 515 break; 516 } 517 break; 518//-------------- 519 case CHANGE_FILE_SAMPLE_SYNTH : 520 if (msg->FindPointer("source", (void**)&item) == B_OK) 521 { 522 BString path = BString(BEOS_SYNTH_DIRECTORY); 523 path += item->Label(); 524 BEntry entry = BEntry(path.String()); 525 if (entry.InitCheck() == B_OK) 526 { 527 entry_ref ref; 528 be_synth->Unload(); 529 entry.GetRef(&ref); 530 be_synth->LoadSynthData(&ref); 531 ((BMidiSynth*)fMidiOutput)->EnableInput(true, true); 532 if (!be_synth->IsLoaded()) 533 { 534 (new BAlert(NULL, "Instrument File can't be loaded correctly", "OK"))->Go(); 535 } 536 ((BMidiSynthFile*)fMidiOutput)->LoadFile(&fOutputFile); 537 ((BMidiSynthFile*)fMidiOutput)->Start(); 538 } 539 else 540 { 541 (new BAlert(NULL, "Can't initialise instrument File", "OK"))->Go(); 542 } 543 } 544 break; 545//-------------- 546 case CHANGE_VOLUME_SYNTH : 547 msg->FindInt32("be:value", (int32*)&temp); 548 be_synth->SetSynthVolume(temp / 1000.0); 549 break; 550//-------------- 551//-------------- 552//For the drag and drop function 553//-------------- 554 case B_SIMPLE_DATA : //A file had been dropped into application 555 if (msg->FindRef("refs", &ref) == B_OK) 556 { 557 message = BMessage(INPUT_CHANGE_TO_FILE); 558 PostMessage(&message); 559 message = BMessage(*msg); 560 message.what = CHANGE_INPUT_FILE; 561 BMessenger messenger(this) 562 fInputFilePanel = new BFilePanel(B_OPEN_PANEL, &messenger, 563 NULL, B_FILE_NODE, false, msg);; 564 PostMessage(&message); 565 message = BMessage(OUTPUT_CHANGE_TO_BEOS_SYNTH); 566 PostMessage(&message); 567 message = BMessage(PLAY_INPUT_FILE); 568 PostMessage(&message); 569 } 570 break; 571//-------------- 572 case B_CANCEL : 573 msg->FindInt32("old_what", (int32*)&temp); 574 if (temp == CHANGE_INPUT_FILE) 575 { 576 delete fInputFilePanel; 577 fInputFilePanel = NULL; 578 } 579 if (temp == CHANGE_OUTPUT_FILE) 580 { 581 delete fOutputFilePanel; 582 fOutputFilePanel = NULL; 583 } 584 break; 585//-------------- 586//-------------- 587//-------------- 588//-------------- 589//-------------- 590//-------------- 591//-------------- 592//-------------- 593//-------------- 594//-------------- 595//-------------- 596//-------------- 597//-------------- 598//-------------- 599//-------------- 600//-------------- 601//-------------- 602//-------------- 603//-------------- 604//-------------- 605//-------------- 606//-------------- 607//-------------- 608//-------------- 609//-------------- 610 default : BWindow::MessageReceived(msg); 611 } 612} 613 614 615//---------------------------------------------------------- 616 617void MidiPlayerWindow::Disconnect(void) 618{//This function must be rewrited for a better disconnection 619 if (fMidiInput != NULL) 620 { 621 fMidiInput->AllNotesOff(false); 622 fMidiInput->Disconnect(fMidiDelay); 623 } 624 if (fMidiOutput != NULL) 625 { 626 fMidiOutput->AllNotesOff(false); 627 fMidiDelay->Disconnect(fMidiOutput); 628 } 629} 630 631//---------------------------------------------------------- 632 633void MidiPlayerWindow::Connect(void) 634{//This function must be rewrited for a better connection 635 if (fMidiInput != NULL) 636 fMidiInput->Connect(fMidiDelay); 637 if (fMidiOutput != NULL) 638 fMidiDelay->Connect(fMidiOutput); 639} 640 641//---------------------------------------------------------- 642//---------------------------------------------------------- 643//---------------------------------------------------------- 644//---------------------------------------------------------- 645//---------------------------------------------------------- 646//---------------------------------------------------------- 647//---------------------------------------------------------- 648//---------------------------------------------------------- 649//---------------------------------------------------------- 650 651int main(int, char**) 652{ 653 MidiPlayerApp *App = new MidiPlayerApp(); 654 App->Run(); 655 delete App; 656 return B_NO_ERROR; 657}; 658 659//---------------------------------------------------------- 660