diff --git a/headers/os/midi/MidiStore.h b/headers/os/midi/MidiStore.h index f5ab7c9850..0076264eff 100644 --- a/headers/os/midi/MidiStore.h +++ b/headers/os/midi/MidiStore.h @@ -9,6 +9,7 @@ struct entry_ref; class BMidiEvent; class BList; +class BFile; class BMidiStore : public BMidi { @@ -78,13 +79,26 @@ private: static int CompareEvents(const void* event1, const void* event2); + void ReadFileHeader(); + void ReadTrackHeader(); + void ReadTrack(); + int32 Read32Bit(); + int16 Read16Bit(); + void ReadData(uint8* data, size_t size); + BList* events; uint32 tempo; uint32 curEvent; uint32 startTime; uint32 ticksPerBeat; - uint32 _reserved[21]; + BFile* file; + int32 numTracks; + int32 trackSize; + int16 division; + + uint16 _reserved1; + uint32 _reserved2[17]; }; #endif // _MIDI_STORE_H diff --git a/src/kits/midi/MidiStore.cpp b/src/kits/midi/MidiStore.cpp index a76a9f36eb..b7b3e02ecb 100644 --- a/src/kits/midi/MidiStore.cpp +++ b/src/kits/midi/MidiStore.cpp @@ -11,8 +11,9 @@ #include #include -#include +#include #include +#include #include "debug.h" #include "MidiEvent.h" @@ -198,9 +199,37 @@ void BMidiStore::AllNotesOff(bool justChannel, uint32 time) status_t BMidiStore::Import(const entry_ref* ref) { - return B_OK; + status_t status = B_OK; + + try + { + file = new BFile(ref, B_READ_ONLY); + + status = file->InitCheck(); + if (status != B_OK) { throw status; } + + ReadFileHeader(); + + for (int32 t = 0; t < numTracks; ++t) + { + TRACE(("[midi] Reading track %d\n", t)) + + ReadTrackHeader(); + ReadTrack(); + } + + SortEvents(true); + } + catch (status_t err) + { + status = err; + } + + delete file; + return status; } + //------------------------------------------------------------------------------ status_t BMidiStore::Export(const entry_ref* ref, int32 format) @@ -336,3 +365,84 @@ int BMidiStore::CompareEvents(const void* event1, const void* event2) //------------------------------------------------------------------------------ +void BMidiStore::ReadFileHeader() +{ + uint8 header[4]; + ReadData(header, 4); + + if (strncmp((char*) header, "MThd", 4) != 0) + { + throw B_BAD_MIDI_DATA; + } + + 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)) +} + +//------------------------------------------------------------------------------ + +void BMidiStore::ReadTrackHeader() +{ + uint8 header[4]; + ReadData(header, 4); + + if (strncmp((char*) header, "MTrk", 4) != 0) + { + throw B_BAD_MIDI_DATA; + } + + trackSize = Read32Bit(); + + TRACE(("[midi] trackSize = %d\n", trackSize)) +} + +//------------------------------------------------------------------------------ + +void BMidiStore::ReadTrack() +{ + /* See */ +} + +//------------------------------------------------------------------------------ + +int32 BMidiStore::Read32Bit() +{ + uint8 buf[4]; + ReadData(buf, 4); + return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; +} + +//------------------------------------------------------------------------------ + +int16 BMidiStore::Read16Bit() +{ + uint8 buf[2]; + ReadData(buf, 2); + return (buf[0] << 8) | buf[1]; +} + +//------------------------------------------------------------------------------ + +void BMidiStore::ReadData(uint8* data, size_t size) +{ + ssize_t res = file->Read(data, size); + + if (res != size) + { + throw (status_t) res; + } +} + +//------------------------------------------------------------------------------ +