From eac71506d6d8d7671fc858cf9d04a53151aebdd7 Mon Sep 17 00:00:00 2001 From: jerl1 Date: Thu, 21 Nov 2002 19:23:22 +0000 Subject: [PATCH] Some correction, and class BMidiStore. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2047 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/midi/Midi.h | 181 +-- headers/os/midi/MidiStore.h | 205 ++- src/kits/midi/Midi.cpp | 317 ++--- src/kits/midi/MidiEvent.cpp | 2 + src/kits/midi/MidiPort.cpp | 4 +- src/kits/midi/MidiPortConsumer.cpp | 2 +- src/kits/midi/MidiStore.cpp | 1133 ++++++++++++----- .../midi/midi_player_replacement/Activity.cpp | 4 +- 8 files changed, 1253 insertions(+), 595 deletions(-) diff --git a/headers/os/midi/Midi.h b/headers/os/midi/Midi.h index ae4a024a50..d296f828bb 100644 --- a/headers/os/midi/Midi.h +++ b/headers/os/midi/Midi.h @@ -1,8 +1,9 @@ - #ifndef _MIDI_H #define _MIDI_H +#ifndef _BE_BUILD_H #include +#endif #include #include @@ -12,115 +13,149 @@ class BList; class BMidi { public: - BMidi(); - virtual ~BMidi(); + BMidi(); +virtual ~BMidi(); - virtual void NoteOff( - uchar channel, uchar note, uchar velocity, uint32 time = B_NOW); +virtual void NoteOff(uchar channel, + uchar note, + uchar velocity, + uint32 time = B_NOW); - virtual void NoteOn( - uchar channel, uchar note, uchar velocity, uint32 time = B_NOW); +virtual void NoteOn(uchar channel, + uchar note, + uchar velocity, + uint32 time = B_NOW); - virtual void KeyPressure( - uchar channel, uchar note, uchar pressure, uint32 time = B_NOW); +virtual void KeyPressure(uchar channel, + uchar note, + uchar pressure, + uint32 time = B_NOW); - virtual void ControlChange( - uchar channel, uchar controlNumber, uchar controlValue, - uint32 time = B_NOW); +virtual void ControlChange(uchar channel, + uchar controlNumber, + uchar controlValue, + uint32 time = B_NOW); - virtual void ProgramChange( - uchar channel, uchar programNumber, uint32 time = B_NOW); +virtual void ProgramChange(uchar channel, + uchar programNumber, + uint32 time = B_NOW); - virtual void ChannelPressure( - uchar channel, uchar pressure, uint32 time = B_NOW); +virtual void ChannelPressure(uchar channel, + uchar pressure, + uint32 time = B_NOW); - virtual void PitchBend( - uchar channel, uchar lsb, uchar msb, uint32 time = B_NOW); +virtual void PitchBend(uchar channel, + uchar lsb, + uchar msb, + uint32 time = B_NOW); - virtual void SystemExclusive( - void* data, size_t dataLength, uint32 time = B_NOW); +virtual void SystemExclusive(void* data, + size_t dataLength, + uint32 time = B_NOW); - virtual void SystemCommon( - uchar status, uchar data1, uchar data2, uint32 time = B_NOW); +virtual void SystemCommon(uchar statusByte, + uchar data1, + uchar data2, + uint32 time = B_NOW); - virtual void SystemRealTime(uchar status, uint32 time = B_NOW); +virtual void SystemRealTime(uchar statusByte, uint32 time = B_NOW); - virtual void TempoChange(int32 beatsPerMinute, uint32 time = B_NOW); +virtual void TempoChange(int32 bpm, uint32 time = B_NOW); - virtual void AllNotesOff(bool justChannel = true, uint32 time = B_NOW); +virtual void AllNotesOff(bool justChannel = true, uint32 time = B_NOW); - virtual status_t Start(); - virtual void Stop(); - bool IsRunning() const; +virtual status_t Start(); +virtual void Stop(); + bool IsRunning() const; - void Connect(BMidi* toObject); - void Disconnect(BMidi* fromObject); - bool IsConnected(BMidi* toObject) const; - BList* Connections() const; + void Connect(BMidi* toObject); + void Disconnect(BMidi* fromObject); + bool IsConnected(BMidi* toObject) const; + BList* Connections() const; - void SnoozeUntil(uint32 time) const; + void SnoozeUntil(uint32 time) const; protected: + void SprayNoteOff(uchar channel, + uchar note, + uchar velocity, + uint32 time) const; - void SprayNoteOff( - uchar channel, uchar note, uchar velocity, uint32 time) const; + void SprayNoteOn(uchar channel, + uchar note, + uchar velocity, + uint32 time) const; - void SprayNoteOn( - uchar channel, uchar note, uchar velocity, uint32 time) const; + void SprayKeyPressure(uchar channel, + uchar note, + uchar pressure, + uint32 time) const; - void SprayKeyPressure( - uchar channel, uchar note, uchar pressure, uint32 time) const; + void SprayControlChange(uchar channel, + uchar controlNumber, + uchar controlValue, + uint32 time) const; - void SprayControlChange( - uchar channel, uchar controlNumber, uchar controlValue, - uint32 time) const; + void SprayProgramChange(uchar channel, + uchar programNumber, + uint32 time) const; - void SprayProgramChange( - uchar channel, uchar programNumber, uint32 time) const; + void SprayChannelPressure(uchar channel, + uchar pressure, + uint32 time) const; - void SprayChannelPressure( - uchar channel, uchar pressure, uint32 time) const; + void SprayPitchBend(uchar channel, + uchar lsb, + uchar msb, + uint32 time) const; - void SprayPitchBend( - uchar channel, uchar lsb, uchar msb, uint32 time) const; + void SpraySystemExclusive(void* data, + size_t dataLength, + uint32 time = B_NOW) const; - void SpraySystemExclusive( - void* data, size_t dataLength, uint32 time = B_NOW) const; + void SpraySystemCommon(uchar statusByte, + uchar data1, + uchar data2, + uint32 time) const; - void SpraySystemCommon( - uchar status, uchar data1, uchar data2, uint32 time) const; + void SpraySystemRealTime(uchar statusByte, uint32 time) const; - void SpraySystemRealTime(uchar status, uint32 time) const; + void SprayTempoChange(int32 bpm, uint32 time) const; - void SprayTempoChange(int32 beatsPerMinute, uint32 time) const; - - bool KeepRunning(); + bool KeepRunning(); private: - friend class BMidiStore; +friend class BMidiPort; /* for debugging */ +friend class BMidiStore; /* for debugging */ - virtual void _ReservedMidi1(); - virtual void _ReservedMidi2(); - virtual void _ReservedMidi3(); +virtual void _ReservedMidi1(); +virtual void _ReservedMidi2(); +virtual void _ReservedMidi3(); - static int32 RunThread(void* data); - static int32 InflowThread(void* data); +friend status_t _run_thread_(void *arg); +friend status_t _inflow_task_(void *arg); - virtual void Run(); - void Inflow(); + void SprayMidiEvent(BMidiEvent* event) const; + port_id ID() const; - void SprayMidiEvent(BMidiEvent* event) const; +virtual void Run(); - BList* connections; - thread_id runThread; - thread_id inflowThread; - port_id inflowPort; - bool isRunning; - bool inflowAlive; + status_t StartInflow(); + void StopInflow(); + bool IsInflowing(); + void InflowTask(); + bool InflowIsAlive(); - uint32 _reserved[5]; + BList* fConnectionList; +volatile thread_id fRunTask; +volatile bool fIsRunning; +volatile thread_id fInflowTask; +volatile bool fInflowAlive; + port_id fInflowPort; + uint32 _reserved[4]; }; -#endif // _MIDI_H + +#endif diff --git a/headers/os/midi/MidiStore.h b/headers/os/midi/MidiStore.h index 0076264eff..4502ed9690 100644 --- a/headers/os/midi/MidiStore.h +++ b/headers/os/midi/MidiStore.h @@ -1,105 +1,178 @@ - #ifndef _MIDI_STORE_H #define _MIDI_STORE_H +#ifndef _BE_BUILD_H #include +#endif #include struct entry_ref; class BMidiEvent; -class BList; class BFile; -class BMidiStore : public BMidi -{ +/*------------------------------------------------------------*/ + +class BMidiStore : public BMidi { public: - BMidiStore(); - virtual ~BMidiStore(); + BMidiStore(); +virtual ~BMidiStore(); - virtual void NoteOff( - uchar channel, uchar note, uchar velocity, uint32 time = B_NOW); +virtual void NoteOff(uchar channel, + uchar note, + uchar velocity, + uint32 time = B_NOW); - virtual void NoteOn( - uchar channel, uchar note, uchar velocity, uint32 time = B_NOW); +virtual void NoteOn(uchar channel, + uchar note, + uchar velocity, + uint32 time = B_NOW); - virtual void KeyPressure( - uchar channel, uchar note, uchar pressure, uint32 time = B_NOW); +virtual void KeyPressure(uchar channel, + uchar note, + uchar pressure, + uint32 time = B_NOW); - virtual void ControlChange( - uchar channel, uchar controlNumber, uchar controlValue, - uint32 time = B_NOW); +virtual void ControlChange(uchar channel, + uchar controlNumber, + uchar controlValue, + uint32 time = B_NOW); - virtual void ProgramChange( - uchar channel, uchar programNumber, uint32 time = B_NOW); +virtual void ProgramChange(uchar channel, + uchar programNumber, + uint32 time = B_NOW); - virtual void ChannelPressure( - uchar channel, uchar pressure, uint32 time = B_NOW); +virtual void ChannelPressure(uchar channel, + uchar pressure, + uint32 time = B_NOW); - virtual void PitchBend( - uchar channel, uchar lsb, uchar msb, uint32 time = B_NOW); +virtual void PitchBend(uchar channel, + uchar lsb, + uchar msb, + uint32 time = B_NOW); - virtual void SystemExclusive( - void* data, size_t dataLength, uint32 time = B_NOW); +virtual void SystemExclusive(void* data, + size_t dataLength, + uint32 time = B_NOW); - virtual void SystemCommon( - uchar status, uchar data1, uchar data2, uint32 time = B_NOW); +virtual void SystemCommon(uchar statusByte, + uchar data1, + uchar data2, + uint32 time = B_NOW); - virtual void SystemRealTime(uchar status, uint32 time = B_NOW); +virtual void SystemRealTime(uchar statusByte, uint32 time = B_NOW); - virtual void TempoChange(int32 beatsPerMinute, uint32 time = B_NOW); +virtual void TempoChange(int32 bpm, uint32 time = B_NOW); - virtual void AllNotesOff(bool justChannel = true, uint32 time = B_NOW); + status_t Import(const entry_ref *ref); + status_t Export(const entry_ref *ref, int32 format); - status_t Import(const entry_ref* ref); - status_t Export(const entry_ref* ref, int32 format); + void SortEvents(bool force=false); + uint32 CountEvents() const; - void SortEvents(bool force = false); - uint32 CountEvents() const; + uint32 CurrentEvent() const; + void SetCurrentEvent(uint32 eventNumber); - uint32 CurrentEvent() const; - void SetCurrentEvent(uint32 eventNumber); + uint32 DeltaOfEvent(uint32 eventNumber) const; + uint32 EventAtDelta(uint32 time) const; - uint32 DeltaOfEvent(uint32 eventNumber) const; - uint32 EventAtDelta(uint32 time) const; - - uint32 BeginTime() const; - - void SetTempo(int32 beatsPerMinute); - int32 Tempo() const; + uint32 BeginTime() const; + + void SetTempo(int32 bpm); + int32 Tempo() const; private: - virtual void _ReservedMidiStore1(); - virtual void _ReservedMidiStore2(); +virtual void _ReservedMidiStore1(); +virtual void _ReservedMidiStore2(); +virtual void _ReservedMidiStore3(); - virtual void Run(); +virtual void Run(); - BMidiEvent* EventAt(uint32 index) const; + void AddEvent(uint32 time, + bool inMS, + uchar type, + uchar data1 = 0, + uchar data2 = 0, + uchar data3 = 0, + uchar data4 = 0); - static int CompareEvents(const void* event1, const void* event2); + void AddSystemExclusive(void* data, size_t dataLength); + + status_t ReadHeader(); + bool ReadMT(char*); + int32 Read32Bit(); + int32 EGetC(); + int32 To32Bit(int32, int32, int32, int32); + int32 Read16Bit(); + int32 To16Bit(int32, int32); + bool ReadTrack(); + int32 ReadVariNum(); + void ChannelMessage(int32, int32, int32); + void MsgInit(); + void MsgAdd(int32); + void BiggerMsg(); + void MetaEvent(int32); + int32 MsgLength(); + uchar* Msg(); + void BadByte(int32); + + int32 PutC(int32 c); + bool WriteTrack(int32 track); + void WriteTempoTrack(); + bool WriteTrackChunk(int32 whichTrack); + void WriteHeaderChunk(int32 format); + bool WriteMidiEvent(uint32 deltaTime, + uint32 type, + uint32 channel, + uchar* data, + uint32 size); + bool WriteMetaEvent(uint32 deltaTime, + uint32 type, + uchar* data, + uint32 size); + bool WriteSystemExclusiveEvent(uint32 deltaTime, + uchar* data, + uint32 size); + void WriteTempo(uint32 deltaTime, int32 tempo); + void WriteVarLen(uint32 value); + void Write32Bit(uint32 data); + void Write16Bit(ushort data); + int32 EPutC(uchar c); + + uint32 TicksToMilliseconds(uint32 ticks) const; + uint32 MillisecondsToTicks(uint32 ms) const; - void ReadFileHeader(); - void ReadTrackHeader(); - void ReadTrack(); - int32 Read32Bit(); - int16 Read16Bit(); - void ReadData(uint8* data, size_t size); + BList *events; +// uint32 fNumEvents; +// uint32 fEventsSize; + uint32 fCurrEvent; + bool fNeedsSorting; +// bool fResetTimer; + uint32 fStartTime; + BFile* fFile; + short fDivision; + float fDivisionFactor; + int32 fTempo; + int32 fCurrTime; + int32 fCurrTrack; + int32 fNumTracks; + +// int32 fToBeRead; +// int32 fMsgIndex; +// int32 fMsgSize; +// uchar* fMsgBuff; + + int32 fNumBytesWritten; - BList* events; - uint32 tempo; - uint32 curEvent; - uint32 startTime; - uint32 ticksPerBeat; - - BFile* file; - int32 numTracks; - int32 trackSize; - int16 division; - - uint16 _reserved1; - uint32 _reserved2[17]; + uchar* fFileBuffer; + int32 fFileBufferMax; + int32 fFileBufferSize; + int32 fFileBufferIndex; + uint32 _reserved[4]; }; -#endif // _MIDI_STORE_H +/*------------------------------------------------------------*/ + +#endif diff --git a/src/kits/midi/Midi.cpp b/src/kits/midi/Midi.cpp index 3e6c22ab4e..cc1d96a14f 100644 --- a/src/kits/midi/Midi.cpp +++ b/src/kits/midi/Midi.cpp @@ -8,128 +8,170 @@ #include -#include "debug.h" #include "Midi.h" +#include "debug.h" #include "MidiEvent.h" -#define MSG_CODE_PROCESS_EVENT 1 -#define MSG_CODE_TERMINATE_THREAD 0 +#define DEBUG -//------------------------------------------------------------------------------ +//----------------------------------------------- +#define MSG_CODE_PROCESS_EVENT 1 +#define MSG_CODE_TERMINATE_THREAD 0 + +//----------------------------------------------- + +//----------------------------------------------------------------------------- +// Initialization Stuff BMidi::BMidi() { - connections = new BList(); - isRunning = false; - - inflowPort = create_port(1, "Inflow Port"); - - inflowThread = spawn_thread( - InflowThread, "BMidi Inflow Thread", - B_REAL_TIME_PRIORITY, (void*) this); - - inflowAlive = (resume_thread(inflowThread) == B_OK); + fConnectionList = new BList(); + fIsRunning = false; + + fInflowPort = create_port(1, "Inflow Port"); + + fInflowTask = spawn_thread( + _inflow_task_, "BMidi Inflow Thread", + B_REAL_TIME_PRIORITY, (void *)this); + + fInflowAlive = resume_thread(fInflowTask) == B_OK; } -//------------------------------------------------------------------------------ - BMidi::~BMidi() { - write_port(inflowPort, MSG_CODE_TERMINATE_THREAD, NULL, 0); + write_port(fInflowPort, MSG_CODE_TERMINATE_THREAD, NULL, 0); - status_t exitValue; - wait_for_thread(inflowThread, &exitValue); + status_t exit_value; + wait_for_thread(fInflowTask, &exit_value); - delete_port(inflowPort); - delete connections; + delete_port(fInflowPort); + delete fConnectionList; } -//------------------------------------------------------------------------------ - -void BMidi::NoteOff(uchar, uchar, uchar, uint32) { } -void BMidi::NoteOn(uchar, uchar, uchar, uint32) { } -void BMidi::KeyPressure(uchar, uchar, uchar, uint32) { } -void BMidi::ControlChange(uchar, uchar, uchar, uint32) { } -void BMidi::ProgramChange(uchar, uchar, uint32) { } -void BMidi::ChannelPressure(uchar, uchar, uint32) { } -void BMidi::PitchBend(uchar, uchar, uchar, uint32) { } -void BMidi::SystemExclusive(void*, size_t, uint32) { } -void BMidi::SystemCommon(uchar, uchar, uchar, uint32) { } -void BMidi::SystemRealTime(uchar, uint32) { } -void BMidi::TempoChange(int32, uint32) { } -void BMidi::AllNotesOff(bool, uint32) { } - -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- +// Stubs for midi event hooks. +void BMidi::NoteOff(uchar chan, uchar note, uchar vel, uint32 time) +{ +} +void BMidi::NoteOn(uchar chan, uchar note, uchar vel, uint32 time) +{ +} +void BMidi::KeyPressure(uchar chan, uchar note, uchar pres, uint32 time) +{ +} +void BMidi::ControlChange(uchar chan, uchar ctrl_num, uchar ctrl_val, uint32 time) +{ +} +void BMidi::ProgramChange(uchar chan, uchar prog_num, uint32 time) +{ +} +void BMidi::ChannelPressure(uchar chan, uchar pres, uint32 time) +{ +} +void BMidi::PitchBend(uchar chan, uchar lsb, uchar msb, uint32 time) +{ +} +void BMidi::SystemExclusive(void * data, size_t data_len, uint32 time) +{ +} +void BMidi::SystemCommon(uchar stat_byte, uchar data1, uchar data2, uint32 time) +{ +} +void BMidi::SystemRealTime(uchar stat_byte, uint32 time) +{ +} +void BMidi::TempoChange(int32 bpm, uint32 time) +{ +} +void BMidi::AllNotesOff(bool just_chan, uint32 time) +{ +} +//----------------------------------------------------------------------------- +// Public API Functions status_t BMidi::Start() { - runThread = spawn_thread( - RunThread, "BMidi Run Thread", - B_REAL_TIME_PRIORITY, (void*) this); - - status_t ret = resume_thread(runThread); - - if (ret == B_OK) - { - isRunning = true; + fRunTask = spawn_thread(_run_thread_, + "BMidi Run Thread", B_REAL_TIME_PRIORITY, (void *)this); + fIsRunning = true; + status_t ret = resume_thread(fRunTask); + if(ret != B_OK) + { + fIsRunning = false; } - - return ret; + return B_OK; } -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- void BMidi::Stop() { - status_t exitValue; - wait_for_thread(runThread, &exitValue); - - isRunning = false; + status_t exit_value; + status_t ret; + fIsRunning = false; + ret = wait_for_thread(fRunTask, &exit_value); } - -//------------------------------------------------------------------------------ - + bool BMidi::IsRunning() const { - return isRunning; + thread_info info; + get_thread_info(fRunTask,&info); + if(find_thread("BMidi Run Thread") == fRunTask) + return true; +return false; } -//------------------------------------------------------------------------------ - -void BMidi::Connect(BMidi* toObject) +void BMidi::Connect(BMidi *to_object) { - connections->AddItem(toObject); + fConnectionList->AddItem((void *)to_object); } -//------------------------------------------------------------------------------ - -void BMidi::Disconnect(BMidi* fromObject) +void BMidi::Disconnect(BMidi *from_object) { - connections->RemoveItem(fromObject); + fConnectionList->RemoveItem((void *)from_object); } -//------------------------------------------------------------------------------ - -bool BMidi::IsConnected(BMidi* toObject) const +bool BMidi::IsConnected(BMidi * to_object) const { - return connections->HasItem(toObject); + return fConnectionList->HasItem((void *)to_object); } -//------------------------------------------------------------------------------ - -BList* BMidi::Connections() const +BList * BMidi::Connections() const { - return connections; + return fConnectionList; } -//------------------------------------------------------------------------------ - void BMidi::SnoozeUntil(uint32 time) const { - snooze_until((uint64) time * 1000, B_SYSTEM_TIMEBASE); + snooze_until((uint64)time*1000, B_SYSTEM_TIMEBASE); } -//------------------------------------------------------------------------------ +bool BMidi::KeepRunning() +{ + return fIsRunning; +} + +void BMidi::Run() +{ + while(KeepRunning()) + snooze(50000); +} + +//----------------------------------------------------------------------------- +// Spray Functions +void BMidi::SprayMidiEvent(BMidiEvent *e) const +{ +// TRACE(("Hello")) + int32 num_connections = fConnectionList->CountItems(); + BMidi *m; + for(int32 i = 0; i < num_connections; i++) + { + m = (BMidi *)fConnectionList->ItemAt(i); + write_port(m->fInflowPort, MSG_CODE_PROCESS_EVENT, e, sizeof(BMidiEvent)); + } +} + +//---------------------- void BMidi::SprayNoteOff( uchar channel, uchar note, uchar velocity, uint32 time) const @@ -143,7 +185,7 @@ void BMidi::SprayNoteOff( SprayMidiEvent(&event); } -//------------------------------------------------------------------------------ +//---------------------- void BMidi::SprayNoteOn( uchar channel, uchar note, uchar velocity, uint32 time) const @@ -157,7 +199,7 @@ void BMidi::SprayNoteOn( SprayMidiEvent(&event); } -//------------------------------------------------------------------------------ +//---------------------- void BMidi::SprayKeyPressure( uchar channel, uchar note, uchar pressure, uint32 time) const @@ -171,7 +213,7 @@ void BMidi::SprayKeyPressure( SprayMidiEvent(&event); } -//------------------------------------------------------------------------------ +//---------------------- void BMidi::SprayControlChange( uchar channel, uchar controlNumber, uchar controlValue, @@ -186,7 +228,7 @@ void BMidi::SprayControlChange( SprayMidiEvent(&event); } -//------------------------------------------------------------------------------ +//---------------------- void BMidi::SprayProgramChange( uchar channel, uchar programNumber, uint32 time) const @@ -199,7 +241,7 @@ void BMidi::SprayProgramChange( SprayMidiEvent(&event); } -//------------------------------------------------------------------------------ +//---------------------- void BMidi::SprayChannelPressure( uchar channel, uchar pressure, uint32 time) const @@ -212,7 +254,7 @@ void BMidi::SprayChannelPressure( SprayMidiEvent(&event); } -//------------------------------------------------------------------------------ +//---------------------- void BMidi::SprayPitchBend( uchar channel, uchar lsb, uchar msb, uint32 time) const @@ -226,22 +268,22 @@ void BMidi::SprayPitchBend( SprayMidiEvent(&event); } -//------------------------------------------------------------------------------ +//---------------------- void BMidi::SpraySystemExclusive( - void* data, size_t dataLength, uint32 time) const + void * data, size_t dataLength, uint32 time) const { - //TODO: Should this data be duplicated!!?? - + // Should this data be duplicated!!?? I think Yes. BMidiEvent event; event.time = time; event.opcode = BMidiEvent::OP_SYSTEM_EXCLUSIVE; - event.systemExclusive.data = (uint8*) data; + event.systemExclusive.data = new uint8[dataLength]; + memcpy(event.systemExclusive.data, data, dataLength); event.systemExclusive.dataLength = dataLength; SprayMidiEvent(&event); } -//------------------------------------------------------------------------------ +//---------------------- void BMidi::SpraySystemCommon( uchar status, uchar data1, uchar data2, uint32 time) const @@ -255,7 +297,7 @@ void BMidi::SpraySystemCommon( SprayMidiEvent(&event); } -//------------------------------------------------------------------------------ +//---------------------- void BMidi::SpraySystemRealTime(uchar status, uint32 time) const { @@ -266,7 +308,7 @@ void BMidi::SpraySystemRealTime(uchar status, uint32 time) const SprayMidiEvent(&event); } -//------------------------------------------------------------------------------ +//---------------------- void BMidi::SprayTempoChange(int32 beatsPerMinute, uint32 time) const { @@ -277,44 +319,20 @@ void BMidi::SprayTempoChange(int32 beatsPerMinute, uint32 time) const SprayMidiEvent(&event); } -//------------------------------------------------------------------------------ - -bool BMidi::KeepRunning() -{ - return isRunning; -} - -//------------------------------------------------------------------------------ - -void BMidi::_ReservedMidi1() { } -void BMidi::_ReservedMidi2() { } -void BMidi::_ReservedMidi3() { } - -//------------------------------------------------------------------------------ - -void BMidi::Run() -{ - while (KeepRunning()) - { - snooze(50000); - } -} - -//------------------------------------------------------------------------------ - -void BMidi::Inflow() +//----------------------------------------------------------------------------- +// The Inflow Thread +void BMidi::InflowTask() { BMidiEvent event; int32 code; size_t len; - - while (true) + while(true) { - len = read_port(inflowPort, &code, &event, sizeof(event)); - + len = read_port(fInflowPort, &code, &event, sizeof(BMidiEvent)); + if (code == MSG_CODE_TERMINATE_THREAD) { return; } - if (len != sizeof(event)) { continue; } // ignore errors + if (len != sizeof(BMidiEvent)) { continue; } //ignore errors switch (event.opcode) { @@ -332,7 +350,7 @@ void BMidi::Inflow() break; case BMidiEvent::OP_NOTE_ON: - NoteOff( + NoteOn( event.noteOn.channel, event.noteOn.note, event.noteOn.velocity, @@ -409,38 +427,41 @@ void BMidi::Inflow() } } -//------------------------------------------------------------------------------ +//---------------------- +//---------------------- +//---------------------- +//---------------------- +//---------------------- +//---------------------- +//---------------------- +//---------------------- -void BMidi::SprayMidiEvent(BMidiEvent* event) const +void BMidi::_ReservedMidi1() {} +void BMidi::_ReservedMidi2() {} +void BMidi::_ReservedMidi3() {} + +//---------------------- + +status_t _run_thread_(void *data) { - TRACE(("[midi] BMidi::SprayMidiEvent, event time = %u, " - "current time = %u\n", event->time, B_NOW)) - - int32 count = connections->CountItems(); - - for (int32 i = 0; i < count; ++i) - { - write_port( - ((BMidi*) connections->ItemAt(i))->inflowPort, - MSG_CODE_PROCESS_EVENT, event, sizeof(*event)); - } -} - -//------------------------------------------------------------------------------ - -int32 BMidi::RunThread(void* data) -{ - ((BMidi*) data)->Run(); + ((BMidi*)data)->Run(); return 0; } -//------------------------------------------------------------------------------ +//---------------------- -int32 BMidi::InflowThread(void* data) +status_t _inflow_task_(void * data) { - ((BMidi*) data)->Inflow(); + ((BMidi*)data)->InflowTask(); return 0; } -//------------------------------------------------------------------------------ - +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- diff --git a/src/kits/midi/MidiEvent.cpp b/src/kits/midi/MidiEvent.cpp index 30867a45f8..97bf3f4866 100644 --- a/src/kits/midi/MidiEvent.cpp +++ b/src/kits/midi/MidiEvent.cpp @@ -18,6 +18,8 @@ BMidiEvent::BMidiEvent() BMidiEvent::~BMidiEvent() { + if (opcode == OP_SYSTEM_EXCLUSIVE) + delete systemExclusive.data; } //------------------------------------------------------------------------------ diff --git a/src/kits/midi/MidiPort.cpp b/src/kits/midi/MidiPort.cpp index 88eab47bdd..718eb8b651 100644 --- a/src/kits/midi/MidiPort.cpp +++ b/src/kits/midi/MidiPort.cpp @@ -140,7 +140,7 @@ return fName; void BMidiPort::NoteOff( uchar channel, uchar note, uchar velocity, uint32 time) { - local_source->SprayNoteOff(channel, note, velocity, 0); + local_source->SprayNoteOff(channel, note, velocity, time); } //------------------------------------------------------------------------------ @@ -148,7 +148,7 @@ void BMidiPort::NoteOff( void BMidiPort::NoteOn( uchar channel, uchar note, uchar velocity, uint32 time) { - local_source->SprayNoteOn(channel, note, velocity, 0); + local_source->SprayNoteOn(channel, note, velocity, time); } //------------------------------------------------------------------------------ diff --git a/src/kits/midi/MidiPortConsumer.cpp b/src/kits/midi/MidiPortConsumer.cpp index 2a7adc3ce1..8f181f62b3 100644 --- a/src/kits/midi/MidiPortConsumer.cpp +++ b/src/kits/midi/MidiPortConsumer.cpp @@ -6,7 +6,7 @@ //---------------------------------------- -#include +#include "MidiPortConsumer.h" //---------------------------------------- diff --git a/src/kits/midi/MidiStore.cpp b/src/kits/midi/MidiStore.cpp index b7b3e02ecb..a8ad3c5cf7 100644 --- a/src/kits/midi/MidiStore.cpp +++ b/src/kits/midi/MidiStore.cpp @@ -1,448 +1,975 @@ -/** - * @file MidiStore.cpp - * - * @author Matthijs Hollemans - * @author Jerome Leveque - * @author Paul Stadler - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include "debug.h" -#include "MidiEvent.h" #include "MidiStore.h" +#include "MidiEvent.h" -//------------------------------------------------------------------------------ +#include +#include //For strcmp(...) +#include //For printf(...) +#include +#include + +//----------------------------------------------- +//#define DEBUG +//----------------------------------------------- + +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- + +int CompareEvents(const void* event1, const void* event2) +{ + return ((BMidiEvent*)event1)->time - ((BMidiEvent*)event2)->time; +} + +//----------------------------------------------- BMidiStore::BMidiStore() { events = new BList(); - tempo = 60; - curEvent = 0; + fFile = NULL; + fFileBuffer = NULL; + fFileBufferMax = 0; + fNeedsSorting = false; + fDivision = 480; + fNumTracks = 1; + fStartTime = 0; + fCurrEvent = 0; } -//------------------------------------------------------------------------------ +//----------------------------------------------- BMidiStore::~BMidiStore() { int32 count = events->CountItems(); - for (int i = count - 1; i >= 0; i--) { delete (BMidiEvent*) events->RemoveItem(i); } - delete events; } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::NoteOff( - uchar channel, uchar note, uchar velocity, uint32 time) +void BMidiStore::NoteOff(uchar chan, uchar note, uchar vel, uint32 time) { - BMidiEvent* event = new BMidiEvent; - event->opcode = BMidiEvent::OP_NOTE_OFF; - event->time = B_NOW; - event->noteOff.channel = channel; - event->noteOff.note = note; - event->noteOff.velocity = velocity; - events->AddItem(event); + AddEvent(time, true, BMidiEvent::OP_NOTE_OFF, chan, note, vel); } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::NoteOn( - uchar channel, uchar note, uchar velocity, uint32 time) +void BMidiStore::NoteOn(uchar chan, uchar note, uchar vel, uint32 time) { - BMidiEvent* event = new BMidiEvent; - event->opcode = BMidiEvent::OP_NOTE_ON; - event->time = B_NOW; - event->noteOn.channel = channel; - event->noteOn.note = note; - event->noteOn.velocity = velocity; - events->AddItem(event); + AddEvent(time, true, BMidiEvent::OP_NOTE_ON, chan, note, vel); } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::KeyPressure( - uchar channel, uchar note, uchar pressure, uint32 time) +void BMidiStore::KeyPressure(uchar chan, uchar note, uchar pres, uint32 time) { - BMidiEvent* event = new BMidiEvent; - event->opcode = BMidiEvent::OP_KEY_PRESSURE; - event->time = B_NOW; - event->keyPressure.channel = channel; - event->keyPressure.note = note; - event->keyPressure.pressure = pressure; - events->AddItem(event); + AddEvent(time, true, BMidiEvent::OP_KEY_PRESSURE, chan, note, pres); } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::ControlChange( - uchar channel, uchar controlNumber, uchar controlValue, uint32 time) +void BMidiStore::ControlChange(uchar chan, uchar ctrl_num, uchar ctrl_val, uint32 time) { - BMidiEvent* event = new BMidiEvent; - event->opcode = BMidiEvent::OP_CONTROL_CHANGE; - event->time = B_NOW; - event->controlChange.channel = channel; - event->controlChange.controlNumber = controlNumber; - event->controlChange.controlValue = controlValue; - events->AddItem(event); + AddEvent(time, true, BMidiEvent::OP_CONTROL_CHANGE, chan, ctrl_num, ctrl_val); } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::ProgramChange( - uchar channel, uchar programNumber, uint32 time) +void BMidiStore::ProgramChange(uchar chan, uchar prog_num, uint32 time) { - BMidiEvent* event = new BMidiEvent; - event->opcode = BMidiEvent::OP_PROGRAM_CHANGE; - event->time = B_NOW; - event->programChange.channel = channel; - event->programChange.programNumber = programNumber; - events->AddItem(event); + AddEvent(time, true, BMidiEvent::OP_PROGRAM_CHANGE, chan, prog_num); } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::ChannelPressure(uchar channel, uchar pressure, uint32 time) +void BMidiStore::ChannelPressure(uchar chan, uchar pres, uint32 time) { - BMidiEvent* event = new BMidiEvent; - event->opcode = BMidiEvent::OP_CHANNEL_PRESSURE; - event->time = B_NOW; - event->channelPressure.channel = channel; - event->channelPressure.pressure = pressure; - events->AddItem(event); + AddEvent(time, true, BMidiEvent::OP_CHANNEL_PRESSURE, chan, pres); } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time) +void BMidiStore::PitchBend(uchar chan, uchar lsb, uchar msb, uint32 time) { - BMidiEvent* event = new BMidiEvent; - event->opcode = BMidiEvent::OP_PITCH_BEND; - event->time = B_NOW; - event->pitchBend.channel = channel; - event->pitchBend.lsb = lsb; - event->pitchBend.msb = msb; - events->AddItem(event); + AddEvent(time, true, BMidiEvent::OP_PITCH_BEND, chan, lsb, msb); +} +//----------------------------------------------- + +void BMidiStore::SystemExclusive(void *data, size_t data_len, uint32 time) +{ + BMidiEvent *e = new BMidiEvent; + e->opcode = BMidiEvent::OP_SYSTEM_EXCLUSIVE; + e->time = time; + e->systemExclusive.data = new uint8[data_len]; + memcpy(e->systemExclusive.data, data, data_len); + e->systemExclusive.dataLength = data_len; + AddSystemExclusive(e, sizeof(BMidiEvent)); } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::SystemExclusive(void* data, size_t dataLength, uint32 time) +void BMidiStore::SystemCommon(uchar stat_byte, uchar data1, uchar data2, uint32 time) { - BMidiEvent* event = new BMidiEvent; - event->opcode = BMidiEvent::OP_SYSTEM_EXCLUSIVE; - event->time = B_NOW; - event->systemExclusive.data = (uint8*) data; - event->systemExclusive.dataLength = dataLength; - events->AddItem(event); + AddEvent(time, true, BMidiEvent::OP_SYSTEM_COMMON, stat_byte, data1, data2); } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::SystemCommon( - uchar status, uchar data1, uchar data2, uint32 time) +void BMidiStore::SystemRealTime(uchar stat_byte, uint32 time) { - BMidiEvent* event = new BMidiEvent; - event->opcode = BMidiEvent::OP_SYSTEM_COMMON; - event->time = B_NOW; - event->systemCommon.status = status; - event->systemCommon.data1 = data1; - event->systemCommon.data2 = data2; - events->AddItem(event); + AddEvent(time, true, BMidiEvent::OP_SYSTEM_REAL_TIME, stat_byte); } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::SystemRealTime(uchar status, uint32 time) +void BMidiStore::TempoChange(int32 bpm, uint32 time) { - BMidiEvent* event = new BMidiEvent; - event->opcode = BMidiEvent::OP_SYSTEM_REAL_TIME; - event->time = B_NOW; - event->systemRealTime.status = status; - events->AddItem(event); + AddEvent(time, true, BMidiEvent::OP_TEMPO_CHANGE, bpm); } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::TempoChange(int32 beatsPerMinute, uint32 time) -{ - BMidiEvent* event = new BMidiEvent; - event->opcode = BMidiEvent::OP_TEMPO_CHANGE; - event->time = B_NOW; - event->tempoChange.beatsPerMinute = beatsPerMinute; - events->AddItem(event); -} +status_t BMidiStore::Import(const entry_ref *ref) +{//ToTest +status_t status = B_NO_ERROR; -//------------------------------------------------------------------------------ + fFile = new BFile(ref, B_READ_ONLY); -void BMidiStore::AllNotesOff(bool justChannel, uint32 time) -{ - BMidiEvent* event = new BMidiEvent; - event->opcode = BMidiEvent::OP_ALL_NOTES_OFF; - event->time = B_NOW; - event->allNotesOff.justChannel = justChannel; - events->AddItem(event); -} - -//------------------------------------------------------------------------------ - -status_t BMidiStore::Import(const entry_ref* ref) -{ - status_t status = B_OK; - - try + status = fFile->InitCheck(); + if (status != B_OK) { - file = new BFile(ref, B_READ_ONLY); + delete fFile; + return status; + } - status = file->InitCheck(); - if (status != B_OK) { throw status; } + status = ReadHeader(); + if (status != B_OK) + { + delete fFile; + return status; + } - ReadFileHeader(); + Read16Bit(); //Format of the MidiFile + fNumTracks = Read16Bit(); + fDivision = Read16Bit(); + fDivisionFactor = 1 / fDivision; - for (int32 t = 0; t < numTracks; ++t) + status = B_OK; + for(fCurrTrack = 0; fCurrTrack < fNumTracks; fCurrTrack++) + { + char mtrk[4]; + if (ReadMT(mtrk) == false) { - TRACE(("[midi] Reading track %d\n", t)) + PRINT("Error while reading MTrk\n"); + status = B_BAD_MIDI_DATA; + break; + } + PRINT(("Printing Track %ld\n", fCurrTrack)); - ReadTrackHeader(); - ReadTrack(); - } - - SortEvents(true); + fFileBufferSize = Read32Bit(); + if (fFileBufferSize > fFileBufferMax) + { + fFileBufferMax = fFileBufferSize; + delete fFileBuffer; + fFileBuffer = new uchar[fFileBufferSize]; + } + if (ReadTrack() == false) + { + PRINT(("Error while reading Trak %ld\n", fCurrTrack)); + status = B_BAD_MIDI_DATA; + break; + } } - catch (status_t err) + + delete fFile; + delete fFileBuffer; + fFileBuffer = NULL; + SortEvents(true); +return status; +} + +//----------------------------------------------- + +status_t BMidiStore::Export(const entry_ref *ref, int32 format) +{//ToDo + fFile = new BFile(ref, B_READ_WRITE); + status_t status = fFile->InitCheck(); + if (status != B_OK) { - status = err; + delete fFile; + return status; } - delete file; - return status; + SortEvents(true); + WriteHeaderChunk(format); + +off_t position_of_length = 0; + + if (format == 0) + {//Format is 0 just one track + position_of_length = fFile->Position() + 4; + WriteTrack(-1); + fFile->Seek(position_of_length, SEEK_SET); + Write32Bit(fNumBytesWritten); + fFile->Seek(0, SEEK_END); + } + + if (format == 1) + {//Format is 1, number of track is fNumTracks initialized when import file + for (int32 i = 0; i < fNumTracks; i++) + { + position_of_length = fFile->Position() + 4; + WriteTrack(i); + fFile->Seek(position_of_length, SEEK_SET); + Write32Bit(fNumBytesWritten); + fFile->Seek(0, SEEK_END); + } + } + +return B_OK; } - -//------------------------------------------------------------------------------ - -status_t BMidiStore::Export(const entry_ref* ref, int32 format) -{ - return B_OK; -} - -//------------------------------------------------------------------------------ +//----------------------------------------------- void BMidiStore::SortEvents(bool force) { events->SortItems(CompareEvents); } -//------------------------------------------------------------------------------ +//----------------------------------------------- uint32 BMidiStore::CountEvents() const -{ - return events->CountItems(); +{//ToTest +return events->CountItems(); } -//------------------------------------------------------------------------------ +//----------------------------------------------- uint32 BMidiStore::CurrentEvent() const -{ - return curEvent; +{//ToTest + return fCurrEvent; } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::SetCurrentEvent(uint32 eventNumber) -{ - curEvent = eventNumber; +void BMidiStore::SetCurrentEvent(uint32 event_num) +{//ToTest + fCurrEvent = event_num; } -//------------------------------------------------------------------------------ +//----------------------------------------------- -uint32 BMidiStore::DeltaOfEvent(uint32 eventNumber) const -{ - BMidiEvent* first = EventAt(0); - - if (first == NULL) { return 0; } - - BMidiEvent* event = EventAt(eventNumber); - - if (event == NULL) { return 0; } - - return event->time - first->time; +uint32 BMidiStore::DeltaOfEvent(uint32 event_num) const +{//ToDo +return 0; } -//------------------------------------------------------------------------------ +//----------------------------------------------- uint32 BMidiStore::EventAtDelta(uint32 time) const -{ - uint32 count = CountEvents(); - uint32 delta = 0; - - for (uint32 t = 0; t < count; ++t) - { - if (delta >= time) - { - return t; - } - else - { - delta += EventAt(t)->time; - } - } - - return 0; +{//ToDo +return 0; } -//------------------------------------------------------------------------------ +//----------------------------------------------- uint32 BMidiStore::BeginTime() const -{ - return startTime; +{//ToTest + return fStartTime; } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::SetTempo(int32 beatsPerMinute) -{ - tempo = beatsPerMinute; +void BMidiStore::SetTempo(int32 bpm) +{//ToTest + fTempo = bpm; } -//------------------------------------------------------------------------------ +//----------------------------------------------- int32 BMidiStore::Tempo() const -{ - return tempo; +{//ToTest + return fTempo; } -//------------------------------------------------------------------------------ - -void BMidiStore::_ReservedMidiStore1() { } -void BMidiStore::_ReservedMidiStore2() { } - -//------------------------------------------------------------------------------ +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- void BMidiStore::Run() { - startTime = B_NOW; - - while (KeepRunning()) + fStartTime = B_NOW; + SortEvents(true); + while (KeepRunning()) { - BMidiEvent* event = EventAt(curEvent); + BMidiEvent* event = (BMidiEvent*)events->ItemAt(fCurrEvent); - if (event == NULL) { return; } + if (event == NULL) return; - uint32 oldTime = event->time; - event->time += startTime; - SprayMidiEvent(event); - event->time = oldTime; + printf("Curr Event : %ld, Time : %ld\n", fCurrEvent, event->time); - ++curEvent; + fCurrTime = event->time; + event->time += fStartTime; +// SprayMidiEvent(event); + event->time = fCurrTime; + + fCurrEvent++; } } -//------------------------------------------------------------------------------ +//----------------------------------------------- -BMidiEvent* BMidiStore::EventAt(uint32 index) const -{ - return (BMidiEvent*) events->ItemAt(index); -} - -//------------------------------------------------------------------------------ - -int BMidiStore::CompareEvents(const void* event1, const void* event2) -{ - return ((BMidiEvent*) event1)->time - ((BMidiEvent*) event2)->time; -} - -//------------------------------------------------------------------------------ - -void BMidiStore::ReadFileHeader() -{ - uint8 header[4]; - ReadData(header, 4); - - if (strncmp((char*) header, "MThd", 4) != 0) +void BMidiStore::AddEvent(uint32 time, bool inMS, uchar type, uchar data1 = 0, uchar data2 = 0, uchar data3 = 0, uchar data4 = 0) +{//ToTest + if (!inMS) { - throw B_BAD_MIDI_DATA; + time = TicksToMilliseconds(time); } - - int32 length = Read32Bit(); - - if (length != 6) { throw B_BAD_MIDI_DATA; } - - Read16Bit(); // skip format - - numTracks = Read16Bit(); - division = Read16Bit(); - - if (numTracks == 0) { throw B_BAD_MIDI_DATA; } - if (division == 0) { throw B_BAD_MIDI_DATA; } - - TRACE(("[midi] numTracks = %d, division = %d\n", numTracks, division)) + BMidiEvent *e = new BMidiEvent(); + e->time = time; + switch (type) + { + case BMidiEvent::OP_NOTE_OFF : + e->opcode = BMidiEvent::OP_NOTE_OFF; + e->noteOff.channel = data1; + e->noteOff.note = data2; + e->noteOff.velocity = data3; + break; + case BMidiEvent::OP_NOTE_ON : + e->opcode = BMidiEvent::OP_NOTE_ON; + e->noteOn.channel = data1; + e->noteOn.note = data2; + e->noteOn.velocity = data3; + break; + case BMidiEvent::OP_KEY_PRESSURE : + e->opcode = BMidiEvent::OP_KEY_PRESSURE; + e->keyPressure.channel = data1; + e->keyPressure.note = data2; + e->keyPressure.pressure = data3; + break; + case BMidiEvent::OP_CONTROL_CHANGE : + e->opcode = BMidiEvent::OP_CONTROL_CHANGE; + e->controlChange.channel = data1; + e->controlChange.controlNumber = data2; + e->controlChange.controlValue = data3; + break; + case BMidiEvent::OP_PROGRAM_CHANGE : + e->opcode = BMidiEvent::OP_PROGRAM_CHANGE; + e->programChange.channel = data1; + e->programChange.programNumber = data2; + break; + case BMidiEvent::OP_CHANNEL_PRESSURE : + e->opcode = BMidiEvent::OP_CHANNEL_PRESSURE; + e->channelPressure.channel = data1; + e->channelPressure.pressure = data2; + break; + case BMidiEvent::OP_PITCH_BEND : + e->opcode = BMidiEvent::OP_PITCH_BEND; + e->pitchBend.channel = data1; + e->pitchBend.lsb = data2; + e->pitchBend.msb = data3; + break; + case BMidiEvent::OP_SYSTEM_COMMON : + e->opcode = BMidiEvent::OP_SYSTEM_COMMON; + e->systemCommon.status = data1; + e->systemCommon.data1 = data2; + e->systemCommon.data2 = data3; + break; + case BMidiEvent::OP_SYSTEM_REAL_TIME : + e->opcode = BMidiEvent::OP_SYSTEM_REAL_TIME; + e->systemRealTime.status = data1; + break; + case BMidiEvent::OP_TEMPO_CHANGE : + e->opcode = BMidiEvent::OP_TEMPO_CHANGE; + e->tempoChange.beatsPerMinute = data1; + break; + case BMidiEvent::OP_ALL_NOTES_OFF : + e->opcode = BMidiEvent::OP_ALL_NOTES_OFF; + e->allNotesOff.justChannel = data1; + break; + default : + delete e; + return; + } + events->AddItem(e); } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::ReadTrackHeader() -{ - uint8 header[4]; - ReadData(header, 4); +void BMidiStore::AddSystemExclusive(void* data, size_t dataLength) +{//ToTest +// BMidiEvent *e = new BMidiEvent(); +// e->time = 0; +// e->systemExclusive.data = (uint8*)data; +// e->systemExclusive.dataLength = dataLength; + events->AddItem(data); +} - if (strncmp((char*) header, "MTrk", 4) != 0) +//----------------------------------------------- + +status_t BMidiStore::ReadHeader() +{//ToTest +char mthd[4]; + if (ReadMT(mthd) == false) + return B_ERROR; + if(strncmp(mthd, "MThd", 4) != 0) { - throw B_BAD_MIDI_DATA; + return B_BAD_MIDI_DATA; } - trackSize = Read32Bit(); - - TRACE(("[midi] trackSize = %d\n", trackSize)) -} - -//------------------------------------------------------------------------------ - -void BMidiStore::ReadTrack() -{ - /* See */ +int32 length = Read32Bit(); + if (length != 6) + { + return B_BAD_MIDI_DATA; + } +return B_OK; } -//------------------------------------------------------------------------------ +//----------------------------------------------- + +bool BMidiStore::ReadMT(char *data) +{//ToTest + return fFile->Read(data, 4) == 4; +} + +//----------------------------------------------- int32 BMidiStore::Read32Bit() -{ - uint8 buf[4]; - ReadData(buf, 4); - return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; +{//ToTest +uchar char32bit[4]; + fFile->Read(char32bit, 4); +return To32Bit(char32bit[0], char32bit[1], char32bit[2], char32bit[3]); } -//------------------------------------------------------------------------------ +//----------------------------------------------- -int16 BMidiStore::Read16Bit() -{ - uint8 buf[2]; - ReadData(buf, 2); - return (buf[0] << 8) | buf[1]; +int32 BMidiStore::EGetC() +{//ToDo +return 0; } -//------------------------------------------------------------------------------ +//----------------------------------------------- -void BMidiStore::ReadData(uint8* data, size_t size) -{ - ssize_t res = file->Read(data, size); +int32 BMidiStore::To32Bit(int32 data1, int32 data2, int32 data3, int32 data4) +{//ToTest + return data1 << 24 | data2 << 16 | data3 << 8 | data4; +} - if (res != size) +//----------------------------------------------- + +int32 BMidiStore::Read16Bit() +{//ToTest +uchar char16bit[2]; + fFile->Read(char16bit, 2); +return To16Bit(char16bit[0], char16bit[1]); +} + +//----------------------------------------------- + +int32 BMidiStore::To16Bit(int32 data1, int32 data2) +{//ToTest + return (uint32)data1 << 8 | (uint32)data2; +} + +//----------------------------------------------- + +bool BMidiStore::ReadTrack() +{//ToTest + if (fFile->Read(fFileBuffer, fFileBufferSize) != fFileBufferSize) + return false; +fNeedsSorting = true; +fFileBufferIndex = 0; +uint32 ticks = 0; +uint32 time = 0; //in ms +uchar data = 0; +uint32 ForTempo = 0; +//fStartTime = 0; + while (fFileBufferIndex < (fFileBufferSize - 3)) { - throw (status_t) res; + ticks += ReadVariNum(); + time = /*fStartTime + */TicksToMilliseconds(ticks); + uchar temp = fFileBuffer[fFileBufferIndex]; + if (temp > 0x7F) + { + data = temp; + fFileBufferIndex++; + } + if (data < 0x80) + { + PRINT(("Big Problem, data : %d, Index : %ld\n", data, fFileBufferIndex)); + return false; + } + switch (data & 0xF0) + { + case B_NOTE_OFF : + NoteOff(data & 0x0F, fFileBuffer[fFileBufferIndex], + fFileBuffer[fFileBufferIndex + 1], time); + fFileBufferIndex += 2; + break; + case B_NOTE_ON : + NoteOn(data & 0x0F, fFileBuffer[fFileBufferIndex], + fFileBuffer[fFileBufferIndex + 1], time); + fFileBufferIndex += 2; + break; + case B_KEY_PRESSURE : + KeyPressure(data & 0x0F, fFileBuffer[fFileBufferIndex], + fFileBuffer[fFileBufferIndex + 1], time); + fFileBufferIndex += 2; + break; + case B_CONTROL_CHANGE : + ControlChange(data & 0x0F, fFileBuffer[fFileBufferIndex], + fFileBuffer[fFileBufferIndex + 1], time); + fFileBufferIndex += 2; + break; + case B_PITCH_BEND : + PitchBend(data & 0x0F, fFileBuffer[fFileBufferIndex], + fFileBuffer[fFileBufferIndex + 1], time); + fFileBufferIndex += 2; + break; + case B_PROGRAM_CHANGE : + ProgramChange(data & 0x0F, fFileBuffer[fFileBufferIndex], time); + fFileBufferIndex += 2; + break; + case B_CHANNEL_PRESSURE : + ChannelPressure(data & 0x0F, fFileBuffer[fFileBufferIndex], time); + fFileBufferIndex += 1; + break; + } + switch (data) + { + case B_SYS_EX_START : + temp = MsgLength(); + SystemExclusive(&fFileBuffer[fFileBufferIndex - 1], temp + 2, time); + fFileBufferIndex += temp; + break; + case B_SONG_POSITION : + SystemCommon(data, fFileBuffer[fFileBufferIndex], fFileBuffer[fFileBufferIndex + 1], time); + fFileBufferIndex += 2; + break; + case B_MIDI_TIME_CODE : + case B_SONG_SELECT : + SystemCommon(data, fFileBuffer[fFileBufferIndex], 0, time); + fFileBufferIndex += 1; + break; + case B_TUNE_REQUEST : + case B_TIMING_CLOCK : + SystemCommon(data, 0, 0, time); + break; + case B_START : + case B_CONTINUE : + case B_STOP : + case B_ACTIVE_SENSING : + SystemRealTime(data, time); + break; + case B_SYSTEM_RESET : + temp = fFileBuffer[fFileBufferIndex]; + if (temp == 0x2F) + return true; + if (temp == 0x51) + {//Calcul of the tempo is wrong + fFileBufferIndex +=2; + ForTempo = fFileBuffer[fFileBufferIndex++] << 8; + ForTempo |= fFileBuffer[fFileBufferIndex++]; + ForTempo = (ForTempo << 8) | fFileBuffer[fFileBufferIndex++]; +// ForTempo /= 2500; + TempoChange(ForTempo, time); + } + else + { + temp = fFileBuffer[fFileBufferIndex + 1] + 3; + SystemExclusive(&fFileBuffer[fFileBufferIndex - 1], temp, time); + fFileBufferIndex += temp - 1; + } + break; + default : + if (data >= 0xF0) + printf("Midi Data not Defined\n"); + } + } +return true; +} + +//----------------------------------------------- + +int32 BMidiStore::ReadVariNum() +{//ToTest +int32 result = 0; +uchar tempo = 0; + while (fFileBufferIndex < fFileBufferSize) + { + tempo = fFileBuffer[fFileBufferIndex++]; + result |= tempo & 0x7F; + if ((tempo & 0x80) == 0) + return result; + result <<= 7; + } +return B_ERROR; +} + +//----------------------------------------------- + +void BMidiStore::ChannelMessage(int32, int32, int32) +{//ToDo + +} + +//----------------------------------------------- + +void BMidiStore::MsgInit() +{//ToDo + +} + +//----------------------------------------------- + +void BMidiStore::MsgAdd(int32) +{//ToDo + +} + +//----------------------------------------------- + +void BMidiStore::BiggerMsg() +{//ToDo + +} + +//----------------------------------------------- + +void BMidiStore::MetaEvent(int32) +{//ToDo + +} + +//----------------------------------------------- + +int32 BMidiStore::MsgLength() +{//ToTest +int32 t = 0; + while (fFileBuffer[fFileBufferIndex + t] != 0xF7) + { + if (fFileBufferIndex + t > fFileBufferSize - 3) + return -1; + else + t++; + } +return t; +} + +//----------------------------------------------- + +uchar *BMidiStore::Msg() +{//ToDo +return 0; +} + +//----------------------------------------------- + +void BMidiStore::BadByte(int32) +{//ToDo + +} + +//----------------------------------------------- + + +int32 BMidiStore::PutC(int32 c) +{//ToDo +return 0; +} + +//----------------------------------------------- + +bool BMidiStore::WriteTrack(int32 track) +{//ToTest +uchar temp[4] = {0x00, 0x00, 0x00, 0x00}; + WriteTrackChunk(track); + fNumBytesWritten = 0; +uint32 ticks = 0; +int32 i = 0; +// If track == -1 write all events +BMidiEvent *event = (BMidiEvent*)events->ItemAt(i++); + if (event != NULL) + fCurrTime = event->time; + while (event != NULL) + { + ticks = MillisecondsToTicks(event->time - fCurrTime); + switch(event->opcode) + { + case BMidiEvent::OP_NOTE_OFF : + if ((track == -1) || (track == event->noteOff.channel)) + { + temp[0] = event->noteOff.note; + temp[1] = event->noteOff.velocity; + WriteMidiEvent(ticks, B_NOTE_OFF, event->noteOff.channel, temp, 2); + } + break; + case BMidiEvent::OP_NOTE_ON : + if ((track == -1) || (track == event->noteOn.channel)) + { + temp[0] = event->noteOn.note; + temp[1] = event->noteOn.velocity; + WriteMidiEvent(ticks, B_NOTE_ON, event->noteOn.channel, temp, 2); + } + break; + case BMidiEvent::OP_KEY_PRESSURE : + if ((track == -1) || (track == event->keyPressure.channel)) + { + temp[0] = event->keyPressure.note; + temp[1] = event->keyPressure.pressure; + WriteMidiEvent(ticks, B_KEY_PRESSURE, event->keyPressure.channel, temp, 2); + } + break; + case BMidiEvent::OP_CONTROL_CHANGE : + if ((track == -1) || (track == event->controlChange.channel)) + { + temp[0] = event->controlChange.controlNumber; + temp[1] = event->controlChange.controlValue; + WriteMidiEvent(ticks, B_CONTROL_CHANGE, event->controlChange.channel, temp, 2); + } + break; + case BMidiEvent::OP_PROGRAM_CHANGE : + if ((track == -1) || (track == event->programChange.channel)) + { + temp[0] = event->programChange.programNumber; + WriteMidiEvent(ticks, B_PROGRAM_CHANGE, event->programChange.channel, temp, 1); + } + break; + case BMidiEvent::OP_CHANNEL_PRESSURE : + if ((track == -1) || (track == event->channelPressure.channel)) + { + temp[0] = event->channelPressure.pressure; + WriteMidiEvent(ticks, B_CHANNEL_PRESSURE, event->channelPressure.channel, temp, 1); + } + break; + case BMidiEvent::OP_PITCH_BEND : + if ((track == -1) || (track == event->pitchBend.channel)) + { + temp[0] = event->pitchBend.lsb; + temp[1] = event->pitchBend.msb; + WriteMidiEvent(ticks, B_PITCH_BEND, event->pitchBend.channel, temp, 2); + } + break; + case BMidiEvent::OP_SYSTEM_COMMON : + if ((track == -1) || (track == 0)) + { + temp[0] = event->systemCommon.data1; + temp[1] = event->systemCommon.data2; + WriteMetaEvent(ticks, event->systemCommon.status, temp, 2); + } + break; + case BMidiEvent::OP_SYSTEM_REAL_TIME : + if ((track == -1) || (track == 0)) + { + WriteMetaEvent(ticks, event->systemRealTime.status, temp, 0); + } + break; + case BMidiEvent::OP_SYSTEM_EXCLUSIVE : + if ((track == -1) || (track == 0)) + { + WriteSystemExclusiveEvent(ticks, event->systemExclusive.data, event->systemExclusive.dataLength); + } + break; + case BMidiEvent::OP_TEMPO_CHANGE : + if ((track == -1) || (track == 0)) + { + WriteTempo(ticks, event->tempoChange.beatsPerMinute); + } + break; +//Not used + case BMidiEvent::OP_NONE : + case BMidiEvent::OP_ALL_NOTES_OFF : + case BMidiEvent::OP_TRACK_END : + break; + } +// } + fCurrTime = event->time; + event = (BMidiEvent*)events->ItemAt(i++); + } + + Write16Bit(0xFF2F); + EPutC(0); +return true; +} + +//----------------------------------------------- + +void BMidiStore::WriteTempoTrack() +{//ToDo +} + +//----------------------------------------------- + +bool BMidiStore::WriteTrackChunk(int32 whichTrack) +{//ToTest + Write32Bit('MTrk'); + Write32Bit(6); +return true; +} + +//----------------------------------------------- + +void BMidiStore::WriteHeaderChunk(int32 format) +{//ToTest + Write32Bit('MThd'); + Write32Bit(6); + Write16Bit(format); + if (format == 0) + fNumTracks = 1; + Write16Bit(fNumTracks); + Write16Bit(fDivision); +} + +//----------------------------------------------- + +bool BMidiStore::WriteMidiEvent(uint32 deltaTime, uint32 type, uint32 channel, uchar* data, uint32 size) +{//ToTest + WriteVarLen(deltaTime); + if (EPutC(type | channel) != 1) + return false; + while (size > 0) + { + if (EPutC(*data) != 1) + return false; + data++; + size--; + } +return true; +} + +//----------------------------------------------- + +bool BMidiStore::WriteMetaEvent(uint32 deltaTime, uint32 type, uchar* data, uint32 size) +{//ToTest + WriteVarLen(deltaTime); + if (EPutC(type) != 1) + return false; + while (size > 0) + { + if (EPutC(*data) != 1) + return false; + data++; + size--; + } +return true; +} + +//----------------------------------------------- + +bool BMidiStore::WriteSystemExclusiveEvent(uint32 deltaTime, uchar* data, uint32 size) +{//ToTest + WriteVarLen(deltaTime); + while (size > 0) + { + if (EPutC(*data) != 1) + return false; + data++; + size--; + } +return true; +} + +//----------------------------------------------- + +void BMidiStore::WriteTempo(uint32 deltaTime, int32 tempo) +{//ToTest + WriteVarLen(deltaTime); + Write16Bit(0xFF51); + EPutC(3); + EPutC((tempo >> 16) & 0xFF); + EPutC((tempo >> 8) & 0xFF); + EPutC(tempo & 0xFF); +} + +//----------------------------------------------- + +void BMidiStore::WriteVarLen(uint32 value) +{//ToTest +uint32 buffer = value & 0x7F; + while ( (value >>= 7) ) + { + buffer <<= 8; + buffer |= ((value & 0x7F) | 0x80); + } + while (true) + { + EPutC(buffer); + if (buffer & 0x80) + buffer >>= 8; + else + break; } } -//------------------------------------------------------------------------------ +//----------------------------------------------- +void BMidiStore::Write32Bit(uint32 data) +{//ToTest + EPutC((data >> 24) & 0xFF); + EPutC((data >> 16) & 0xFF); + EPutC((data >> 8) & 0xFF); + EPutC(data & 0xFF); +} + +//----------------------------------------------- + +void BMidiStore::Write16Bit(ushort data) +{//ToTest + EPutC((data >> 8) & 0xFF); + EPutC(data & 0xFF); +} + +//----------------------------------------------- + +int32 BMidiStore::EPutC(uchar c) +{//ToTest + fNumBytesWritten++; +return fFile->Write(&c, 1); +} + +//----------------------------------------------- + + +uint32 BMidiStore::TicksToMilliseconds(uint32 ticks) const +{//ToTest + return ((uint64)ticks * 1000) / fDivision; +} + +//----------------------------------------------- + +uint32 BMidiStore::MillisecondsToTicks(uint32 ms) const +{//ToTest + return ((uint64)ms * fDivision) / 1000; +} + +//----------------------------------------------- + +void BMidiStore::_ReservedMidiStore1() +{ +} + +//----------------------------------------------- + +void BMidiStore::_ReservedMidiStore2() +{ +} + +//----------------------------------------------- + +void BMidiStore::_ReservedMidiStore3() +{ +} + +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- +//----------------------------------------------- diff --git a/src/tests/kits/midi/midi_player_replacement/Activity.cpp b/src/tests/kits/midi/midi_player_replacement/Activity.cpp index cdd1586fe9..24dbd64e3b 100644 --- a/src/tests/kits/midi/midi_player_replacement/Activity.cpp +++ b/src/tests/kits/midi/midi_player_replacement/Activity.cpp @@ -74,8 +74,8 @@ void Activity::Pulse(void) void Activity::NoteOn(uchar channel, uchar note, uchar velocity, uint32 time = B_NOW) {//This function just update the variable - fActivity[channel - 1] = system_time(); - BMidi::NoteOn(channel, note, velocity, time); + fActivity[channel] = system_time(); + SprayNoteOn(channel, note, velocity, time); } //----------------------------------------------------------