verbosity--
[ardour.git] / libs / evoral / src / SMF.cpp
index f5fff726caccae38adaa59f803fe913a05d5dc53..5d129ce7e79d893971dca2d061c2bb622c6d594d 100644 (file)
@@ -32,8 +32,8 @@ using namespace std;
 
 namespace Evoral {
 
-template<typename T>
-SMF<T>::SMF()
+template<typename Time>
+SMF<Time>::SMF()
        : _fd(0)
        , _last_ev_time(0)
        , _track_size(4) // 4 bytes for the ever-present EOT event
@@ -42,8 +42,8 @@ SMF<T>::SMF()
 {
 }
 
-template<typename T>
-SMF<T>::~SMF()
+template<typename Time>
+SMF<Time>::~SMF()
 {
 }
 
@@ -55,9 +55,10 @@ SMF<T>::~SMF()
  *         -1 if the file can not be opened for reading,
  *         -2 if the file can not be opened for writing
  */
-template<typename T>
+template<typename Time>
 int
-SMF<T>::open(const std::string& path)
+SMF<Time>::open(const std::string& path) THROW_FILE_ERROR
+
 {
        //cerr << "Opening SMF file " << path() << " writeable: " << writable() << endl;
        _fd = fopen(path.c_str(), "r+");
@@ -90,9 +91,9 @@ SMF<T>::open(const std::string& path)
        return (_fd == 0) ? -1 : 0;
 }
 
-template<typename T>
+template<typename Time>
 void
-SMF<T>::close()
+SMF<Time>::close() THROW_FILE_ERROR
 {
        if (_fd) {
                flush_header();
@@ -102,16 +103,16 @@ SMF<T>::close()
        }
 }
 
-template<typename T>
+template<typename Time>
 void
-SMF<T>::seek_to_start() const
+SMF<Time>::seek_to_start() const
 {
        fseek(_fd, _header_size, SEEK_SET);
 }
 
-template<typename T>
+template<typename Time>
 void
-SMF<T>::seek_to_footer_position()
+SMF<Time>::seek_to_footer_position()
 {
        uint8_t buffer[4];
        
@@ -132,16 +133,16 @@ SMF<T>::seek_to_footer_position()
        }
 }
 
-template<typename T>
+template<typename Time>
 void
-SMF<T>::flush()
+SMF<Time>::flush()
 {
        fflush(_fd);
 }
 
-template<typename T>
+template<typename Time>
 int
-SMF<T>::flush_header()
+SMF<Time>::flush_header()
 {
        // FIXME: write timeline position somehow?
        
@@ -169,9 +170,9 @@ SMF<T>::flush_header()
        return 0;
 }
 
-template<typename T>
+template<typename Time>
 int
-SMF<T>::flush_footer()
+SMF<Time>::flush_footer()
 {
        //cerr << path() << " SMF Flushing footer\n";
        seek_to_footer_position();
@@ -181,9 +182,9 @@ SMF<T>::flush_footer()
        return 0;
 }
 
-template<typename T>
+template<typename Time>
 void
-SMF<T>::write_footer()
+SMF<Time>::write_footer()
 {
        write_var_len(0);
        char eot[3] = { 0xFF, 0x2F, 0x00 }; // end-of-track meta-event
@@ -206,9 +207,9 @@ SMF<T>::write_footer()
  * Returns event length (including status byte) on success, 0 if event was
  * skipped (eg a meta event), or -1 on EOF (or end of track).
  */
-template<typename T>
+template<typename Time>
 int
-SMF<T>::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const
+SMF<Time>::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const
 {
        if (feof(_fd)) {
                return -1;
@@ -249,10 +250,14 @@ SMF<T>::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const
                }
        }
        
-       const int event_size = midi_event_size((unsigned char)status);
+       int event_size = midi_event_size((unsigned char)status);
        if (event_size <= 0) {
-               *size = 0;
-               return 0;
+               if ((status & 0xff) == MIDI_CMD_COMMON_SYSEX) {
+               event_size = SMFReader::read_var_len(_fd) + 1;
+               } else {
+                       *size = 0;
+                       return 0;
+               }
        }
        
        // Make sure we have enough scratch buffer
@@ -265,7 +270,7 @@ SMF<T>::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const
        if (event_size > 1)
                fread((*buf) + 1, 1, *size - 1, _fd);
 
-       /*printf("SMF %s read event: delta = %u, size = %u, data = ", _name.c_str(), *delta_t, *size);
+       /*printf("SMF read event: delta = %u, size = %u, data = ",  *delta_t, *size);
        for (size_t i=0; i < *size; ++i) {
                printf("%X ", (*buf)[i]);
        }
@@ -274,15 +279,21 @@ SMF<T>::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const
        return (int)*size;
 }
 
-template<typename T>
+template<typename Time>
 void
-SMF<T>::append_event_unlocked(uint32_t delta_t, const Event<T>& ev)
+SMF<Time>::append_event_delta(uint32_t delta_t, const Event<Time>& ev)
 {
        if (ev.size() == 0)
                return;
-
-       const size_t stamp_size = write_var_len(delta_t);
-       fwrite(ev.buffer(), 1, ev.size(), _fd);
+       
+       size_t stamp_size = write_var_len(delta_t);
+       if (ev.buffer()[0] == MIDI_CMD_COMMON_SYSEX) {
+               fputc(MIDI_CMD_COMMON_SYSEX, _fd);
+               stamp_size += write_var_len(ev.size() - 1);
+               fwrite(ev.buffer() + 1, 1, ev.size() - 1, _fd);
+       } else {
+               fwrite(ev.buffer(), 1, ev.size(), _fd);
+       }
 
        _track_size += stamp_size + ev.size();
        _last_ev_time = ev.time();
@@ -291,25 +302,25 @@ SMF<T>::append_event_unlocked(uint32_t delta_t, const Event<T>& ev)
                _empty = false;
 }
 
-template<typename T>
+template<typename Time>
 void
-SMF<T>::begin_write(FrameTime start_frame)
+SMF<Time>::begin_write()
 {
        _last_ev_time = 0;
        fseek(_fd, _header_size, SEEK_SET);
 }
 
-template<typename T>
+template<typename Time>
 void
-SMF<T>::end_write()
+SMF<Time>::end_write() throw(typename MIDIFile<Time>::FileError)
 {
        flush_header();
        flush_footer();
 }
 
-template<typename T>
+template<typename Time>
 void
-SMF<T>::write_chunk_header(const char id[4], uint32_t length)
+SMF<Time>::write_chunk_header(const char id[4], uint32_t length)
 {
        const uint32_t length_be = GUINT32_TO_BE(length);
 
@@ -317,9 +328,9 @@ SMF<T>::write_chunk_header(const char id[4], uint32_t length)
        fwrite(&length_be, 4, 1, _fd);
 }
 
-template<typename T>
+template<typename Time>
 void
-SMF<T>::write_chunk(const char id[4], uint32_t length, void* data)
+SMF<Time>::write_chunk(const char id[4], uint32_t length, void* data)
 {
        write_chunk_header(id, length);
        
@@ -327,9 +338,9 @@ SMF<T>::write_chunk(const char id[4], uint32_t length, void* data)
 }
 
 /** Returns the size (in bytes) of the value written. */
-template<typename T>
+template<typename Time>
 size_t
-SMF<T>::write_var_len(uint32_t value)
+SMF<Time>::write_var_len(uint32_t value)
 {
        size_t ret = 0;