diff options
author | Robin Gareus <robin@gareus.org> | 2016-10-05 20:08:26 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2016-10-05 20:08:26 +0200 |
commit | 4d66c89b83488777904907682271dfadd1cb04c2 (patch) | |
tree | 81a4003b6d5c651f4f877ec315a21e0c3bded91a | |
parent | f6570bb5070ae217822299492ddeae3ad19bc46f (diff) |
SMF add support for type-0 files (count channels, not tracks)
-rw-r--r-- | libs/evoral/evoral/SMF.hpp | 9 | ||||
-rw-r--r-- | libs/evoral/src/SMF.cpp | 41 |
2 files changed, 49 insertions, 1 deletions
diff --git a/libs/evoral/evoral/SMF.hpp b/libs/evoral/evoral/SMF.hpp index fd7263b5c4..0cbd5bb638 100644 --- a/libs/evoral/evoral/SMF.hpp +++ b/libs/evoral/evoral/SMF.hpp @@ -21,6 +21,7 @@ #define EVORAL_SMF_HPP #include <glibmm/threads.h> +#include <set> #include "evoral/visibility.h" #include "evoral/types.hpp" @@ -49,7 +50,7 @@ public: std::string _file_name; }; - SMF() : _smf(0), _smf_track(0), _empty(true) {}; + SMF(); virtual ~SMF(); static bool test(const std::string& path); @@ -75,11 +76,17 @@ public: double round_to_file_precision (double val) const; + bool is_type0 () const { return _type0; } + std::set<uint8_t> channels () const { return _type0channels; } + private: smf_t* _smf; smf_track_t* _smf_track; bool _empty; ///< true iff file contains(non-empty) events mutable Glib::Threads::Mutex _smf_lock; + + bool _type0; + std::set<uint8_t> _type0channels; }; }; /* namespace Evoral */ diff --git a/libs/evoral/src/SMF.cpp b/libs/evoral/src/SMF.cpp index 65304c4e4d..f5dc4fa1e0 100644 --- a/libs/evoral/src/SMF.cpp +++ b/libs/evoral/src/SMF.cpp @@ -39,6 +39,13 @@ using namespace std; namespace Evoral { +SMF::SMF() + : _smf (0) + , _smf_track (0) + , _empty (true) + , _type0 (false) + {}; + SMF::~SMF() { close (); @@ -107,6 +114,9 @@ SMF::open(const std::string& path, int track) THROW_FILE_ERROR { Glib::Threads::Mutex::Lock lm (_smf_lock); + _type0 = false; + _type0channels.clear (); + assert(track >= 1); if (_smf) { smf_delete(_smf); @@ -133,6 +143,33 @@ SMF::open(const std::string& path, int track) THROW_FILE_ERROR } fclose(f); + + lm.release (); + if (_smf->format == 0 && _smf->number_of_tracks == 1 && !_empty) { + // type-0 file: scan file for # of used channels. + int ret; + uint32_t delta_t = 0; + uint32_t size = 0; + uint8_t* buf = NULL; + event_id_t event_id = 0; + seek_to_start(); + while ((ret = read_event (&delta_t, &size, &buf, &event_id)) >= 0) { + if (ret == 0) { + continue; + } + if (size == 0) { + break; + } + uint8_t type = buf[0] & 0xf0; + uint8_t chan = buf[0] & 0x0f; + if (type < 0x80 || type > 0xE0) { + continue; + } + _type0channels.insert(chan); + } + _type0 = true; + seek_to_start(); + } return 0; } @@ -193,6 +230,8 @@ SMF::create(const std::string& path, int track, uint16_t ppqn) THROW_FILE_ERROR } _empty = true; + _type0 = false; + _type0channels.clear (); return 0; } @@ -206,6 +245,8 @@ SMF::close() THROW_FILE_ERROR smf_delete(_smf); _smf = 0; _smf_track = 0; + _type0 = false; + _type0channels.clear (); } } |