Mercurial > hg > amuse
diff implementations/midi-db/db-insert-functions.lisp @ 236:a5d065905f6d
Add midi-db.
Ignore-this: c6f4fc32efa4453ddbdc478793eedd52
A basic implementation for working with MIDI files stored in the database.
It is a test case for `versioned' data, but only partially implemented at the moment.
darcs-hash:20100223152703-16a00-4388d2720907d777a1c6c6b3a010885ce0fe06a7.gz
committer: Jamie Forth <j.forth@gold.ac.uk>
author | j.forth <j.forth@gold.ac.uk> |
---|---|
date | Thu, 24 Feb 2011 11:23:18 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/implementations/midi-db/db-insert-functions.lisp Thu Feb 24 11:23:18 2011 +0000 @@ -0,0 +1,162 @@ +(cl:in-package #:amuse-midi-db) + +(defun register-new-collection (collection-name description database) + (clsql:with-transaction (:database database) + "Error checking needed for duplicates." + #.(clsql:locally-enable-sql-reader-syntax) + (clsql:insert-records + :into "midi_db_collections" + :attributes '([collection-name] + [description]) + :values (list collection-name description) + :database database) + #.(clsql:locally-disable-sql-reader-syntax) + (make-midi-db-collection-identifier ;return new collection identifier + (clsql-mysql::mysql-insert-id + (clsql-mysql::database-mysql-ptr + database))))) + +(defvar *import-file* (pathname "/tmp/midi-db.txt")) + +(defun import-composition (composition collection-identifier database) + #.(clsql:locally-enable-sql-reader-syntax) + (let* ((collection-id (collection-id collection-identifier)) + (filename (file-namestring (midifile-identifier-pathname + (identifier composition)))) + (timebase (midi-timebase composition)) + (start (* (timepoint composition) timebase)) + (duration (* (duration composition) timebase)) + (composition-id)) + ;; add composition header + (clsql:with-transaction (:database database) + (clsql:insert-records :into "midi_db_compositions" + :attributes '([collection-id] [filename] + [timebase] [start] [duration]) + :values (list collection-id + filename + timebase + start + duration) + :database database) + (setf composition-id (clsql-mysql::mysql-insert-id + (clsql-mysql::database-mysql-ptr + database))) + #.(clsql:locally-disable-sql-reader-syntax) + ;; add tempo, timesig and keysig constituents + (%add-tempo-constituents collection-id composition-id + (tempi composition) timebase database) + (%add-timesig-constituents collection-id composition-id + (time-signatures composition) + timebase database) + (%add-keysig-constituents collection-id composition-id + (key-signatures composition) timebase + database) + (write-to-db-file collection-id composition-id composition) + (clsql:execute-command + (concatenate 'string + "LOAD DATA LOCAL INFILE '" + (namestring *import-file*) + "' INTO TABLE " + "midi_db_events") + :database database) + (delete-file *import-file*) + (format t "Composition added to db, id: ~A~%" composition-id)))) + + +;;;===================================================================== +;;; All the below are just helper functions. +;;;===================================================================== + +(defun write-to-db-file (collection-id composition-id composition) + (let ((timebase (midi-timebase composition))) + (with-open-file (stream *import-file* + :direction :output + :if-exists :supersede + :external-format :latin1) + (sequence:dosequence (event composition) + (format stream + "~S ~S \\N ~{~S ~}1~%" ; 1 is the + ; version number + collection-id composition-id + (if (amuse-utils:pitchedp event) + (list (midi-track event) + (midi-channel event) + (midi-patch event) + (midi-pitch-number event) + (midi-velocity event) + (* (timepoint event) timebase) + (* (duration event) timebase)) + (list (midi-track event) + (midi-channel event) + 0 ;FIXME no patch for perc? + (midi-drum-sound event) + (midi-velocity event) + (* (timepoint event) timebase) + (* (duration event) timebase))))))) + t) + +;;; FIXME: use macros here. + +(defun %add-tempo-constituents (collection-id composition-id tempi timebase + database) + #.(clsql:locally-enable-sql-reader-syntax) + (loop ;with constituent-id + for tempo in tempi + do (clsql:insert-records :into "midi_db_tempi" + :attributes '([collection-id] + [composition-id] + [start] + [duration] + [microsecs-per-crotchet]) + :values (list collection-id + composition-id + (* (timepoint tempo) timebase) + (* (duration tempo) timebase) + (microseconds-per-crotchet + tempo)) + :database database)) + #.(clsql:locally-disable-sql-reader-syntax)) + +(defun %add-timesig-constituents (collection-id composition-id timesigs + timebase database) + #.(clsql:locally-enable-sql-reader-syntax) + (loop for timesig in timesigs + do (clsql:insert-records :into "midi_db_timesigs" + :attributes '([collection-id] + [composition-id] + [start] + [duration] + [numerator] + [denominator]) + :values (list collection-id + composition-id + (* (timepoint timesig) timebase) + (* (duration timesig) timebase) + (time-signature-numerator + timesig) + (time-signature-denominator + timesig)) + :database database)) + #.(clsql:locally-disable-sql-reader-syntax)) + +(defun %add-keysig-constituents (collection-id composition-id keysigs + timebase database) + #.(clsql:locally-enable-sql-reader-syntax) + (loop for keysig in keysigs + do (clsql:insert-records :into "midi_db_keysigs" + :attributes '([collection-id] + [composition-id] + [start] + [duration] + [mode] + [sharp-count]) + :values (list collection-id + composition-id + (* (timepoint keysig) timebase) + (* (duration keysig) timebase) + (key-signature-mode + keysig) + (key-signature-sharps + keysig)) + :database database)) + #.(clsql:locally-disable-sql-reader-syntax))