j@236: (cl:in-package #:amuse-midi-db) j@236: j@236: (defun register-new-collection (collection-name description database) j@236: (clsql:with-transaction (:database database) j@236: "Error checking needed for duplicates." j@236: #.(clsql:locally-enable-sql-reader-syntax) j@236: (clsql:insert-records j@236: :into "midi_db_collections" j@236: :attributes '([collection-name] j@236: [description]) j@236: :values (list collection-name description) j@236: :database database) j@236: #.(clsql:locally-disable-sql-reader-syntax) j@236: (make-midi-db-collection-identifier ;return new collection identifier j@236: (clsql-mysql::mysql-insert-id j@236: (clsql-mysql::database-mysql-ptr j@236: database))))) j@236: j@236: (defvar *import-file* (pathname "/tmp/midi-db.txt")) j@236: j@236: (defun import-composition (composition collection-identifier database) j@236: #.(clsql:locally-enable-sql-reader-syntax) j@236: (let* ((collection-id (collection-id collection-identifier)) j@236: (filename (file-namestring (midifile-identifier-pathname j@236: (identifier composition)))) j@236: (timebase (midi-timebase composition)) j@236: (start (* (timepoint composition) timebase)) j@236: (duration (* (duration composition) timebase)) j@236: (composition-id)) j@236: ;; add composition header j@236: (clsql:with-transaction (:database database) j@236: (clsql:insert-records :into "midi_db_compositions" j@236: :attributes '([collection-id] [filename] j@236: [timebase] [start] [duration]) j@236: :values (list collection-id j@236: filename j@236: timebase j@236: start j@236: duration) j@236: :database database) j@236: (setf composition-id (clsql-mysql::mysql-insert-id j@236: (clsql-mysql::database-mysql-ptr j@236: database))) j@236: #.(clsql:locally-disable-sql-reader-syntax) j@236: ;; add tempo, timesig and keysig constituents j@236: (%add-tempo-constituents collection-id composition-id j@236: (tempi composition) timebase database) j@236: (%add-timesig-constituents collection-id composition-id j@236: (time-signatures composition) j@236: timebase database) j@236: (%add-keysig-constituents collection-id composition-id j@236: (key-signatures composition) timebase j@236: database) j@236: (write-to-db-file collection-id composition-id composition) j@236: (clsql:execute-command j@236: (concatenate 'string j@236: "LOAD DATA LOCAL INFILE '" j@236: (namestring *import-file*) j@236: "' INTO TABLE " j@236: "midi_db_events") j@236: :database database) j@236: (delete-file *import-file*) j@236: (format t "Composition added to db, id: ~A~%" composition-id)))) j@236: j@236: j@236: ;;;===================================================================== j@236: ;;; All the below are just helper functions. j@236: ;;;===================================================================== j@236: j@236: (defun write-to-db-file (collection-id composition-id composition) j@236: (let ((timebase (midi-timebase composition))) j@236: (with-open-file (stream *import-file* j@236: :direction :output j@236: :if-exists :supersede j@236: :external-format :latin1) j@236: (sequence:dosequence (event composition) j@236: (format stream j@236: "~S ~S \\N ~{~S ~}1~%" ; 1 is the j@236: ; version number j@236: collection-id composition-id j@236: (if (amuse-utils:pitchedp event) j@236: (list (midi-track event) j@236: (midi-channel event) j@236: (midi-patch event) j@236: (midi-pitch-number event) j@236: (midi-velocity event) j@236: (* (timepoint event) timebase) j@236: (* (duration event) timebase)) j@236: (list (midi-track event) j@236: (midi-channel event) j@236: 0 ;FIXME no patch for perc? j@236: (midi-drum-sound event) j@236: (midi-velocity event) j@236: (* (timepoint event) timebase) j@236: (* (duration event) timebase))))))) j@236: t) j@236: j@236: ;;; FIXME: use macros here. j@236: j@236: (defun %add-tempo-constituents (collection-id composition-id tempi timebase j@236: database) j@236: #.(clsql:locally-enable-sql-reader-syntax) j@236: (loop ;with constituent-id j@236: for tempo in tempi j@236: do (clsql:insert-records :into "midi_db_tempi" j@236: :attributes '([collection-id] j@236: [composition-id] j@236: [start] j@236: [duration] j@236: [microsecs-per-crotchet]) j@236: :values (list collection-id j@236: composition-id j@236: (* (timepoint tempo) timebase) j@236: (* (duration tempo) timebase) j@236: (microseconds-per-crotchet j@236: tempo)) j@236: :database database)) j@236: #.(clsql:locally-disable-sql-reader-syntax)) j@236: j@236: (defun %add-timesig-constituents (collection-id composition-id timesigs j@236: timebase database) j@236: #.(clsql:locally-enable-sql-reader-syntax) j@236: (loop for timesig in timesigs j@236: do (clsql:insert-records :into "midi_db_timesigs" j@236: :attributes '([collection-id] j@236: [composition-id] j@236: [start] j@236: [duration] j@236: [numerator] j@236: [denominator]) j@236: :values (list collection-id j@236: composition-id j@236: (* (timepoint timesig) timebase) j@236: (* (duration timesig) timebase) j@236: (time-signature-numerator j@236: timesig) j@236: (time-signature-denominator j@236: timesig)) j@236: :database database)) j@236: #.(clsql:locally-disable-sql-reader-syntax)) j@236: j@236: (defun %add-keysig-constituents (collection-id composition-id keysigs j@236: timebase database) j@236: #.(clsql:locally-enable-sql-reader-syntax) j@236: (loop for keysig in keysigs j@236: do (clsql:insert-records :into "midi_db_keysigs" j@236: :attributes '([collection-id] j@236: [composition-id] j@236: [start] j@236: [duration] j@236: [mode] j@236: [sharp-count]) j@236: :values (list collection-id j@236: composition-id j@236: (* (timepoint keysig) timebase) j@236: (* (duration keysig) timebase) j@236: (key-signature-mode j@236: keysig) j@236: (key-signature-sharps j@236: keysig)) j@236: :database database)) j@236: #.(clsql:locally-disable-sql-reader-syntax))