summaryrefslogtreecommitdiff
path: root/libs/evoral
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2016-10-05 20:08:26 +0200
committerRobin Gareus <robin@gareus.org>2016-10-05 20:08:26 +0200
commit4d66c89b83488777904907682271dfadd1cb04c2 (patch)
tree81a4003b6d5c651f4f877ec315a21e0c3bded91a /libs/evoral
parentf6570bb5070ae217822299492ddeae3ad19bc46f (diff)
SMF add support for type-0 files (count channels, not tracks)
Diffstat (limited to 'libs/evoral')
-rw-r--r--libs/evoral/evoral/SMF.hpp9
-rw-r--r--libs/evoral/src/SMF.cpp41
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 ();
}
}