annotate 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
rev   line source
j@236 1 (cl:in-package #:amuse-midi-db)
j@236 2
j@236 3 (defun register-new-collection (collection-name description database)
j@236 4 (clsql:with-transaction (:database database)
j@236 5 "Error checking needed for duplicates."
j@236 6 #.(clsql:locally-enable-sql-reader-syntax)
j@236 7 (clsql:insert-records
j@236 8 :into "midi_db_collections"
j@236 9 :attributes '([collection-name]
j@236 10 [description])
j@236 11 :values (list collection-name description)
j@236 12 :database database)
j@236 13 #.(clsql:locally-disable-sql-reader-syntax)
j@236 14 (make-midi-db-collection-identifier ;return new collection identifier
j@236 15 (clsql-mysql::mysql-insert-id
j@236 16 (clsql-mysql::database-mysql-ptr
j@236 17 database)))))
j@236 18
j@236 19 (defvar *import-file* (pathname "/tmp/midi-db.txt"))
j@236 20
j@236 21 (defun import-composition (composition collection-identifier database)
j@236 22 #.(clsql:locally-enable-sql-reader-syntax)
j@236 23 (let* ((collection-id (collection-id collection-identifier))
j@236 24 (filename (file-namestring (midifile-identifier-pathname
j@236 25 (identifier composition))))
j@236 26 (timebase (midi-timebase composition))
j@236 27 (start (* (timepoint composition) timebase))
j@236 28 (duration (* (duration composition) timebase))
j@236 29 (composition-id))
j@236 30 ;; add composition header
j@236 31 (clsql:with-transaction (:database database)
j@236 32 (clsql:insert-records :into "midi_db_compositions"
j@236 33 :attributes '([collection-id] [filename]
j@236 34 [timebase] [start] [duration])
j@236 35 :values (list collection-id
j@236 36 filename
j@236 37 timebase
j@236 38 start
j@236 39 duration)
j@236 40 :database database)
j@236 41 (setf composition-id (clsql-mysql::mysql-insert-id
j@236 42 (clsql-mysql::database-mysql-ptr
j@236 43 database)))
j@236 44 #.(clsql:locally-disable-sql-reader-syntax)
j@236 45 ;; add tempo, timesig and keysig constituents
j@236 46 (%add-tempo-constituents collection-id composition-id
j@236 47 (tempi composition) timebase database)
j@236 48 (%add-timesig-constituents collection-id composition-id
j@236 49 (time-signatures composition)
j@236 50 timebase database)
j@236 51 (%add-keysig-constituents collection-id composition-id
j@236 52 (key-signatures composition) timebase
j@236 53 database)
j@236 54 (write-to-db-file collection-id composition-id composition)
j@236 55 (clsql:execute-command
j@236 56 (concatenate 'string
j@236 57 "LOAD DATA LOCAL INFILE '"
j@236 58 (namestring *import-file*)
j@236 59 "' INTO TABLE "
j@236 60 "midi_db_events")
j@236 61 :database database)
j@236 62 (delete-file *import-file*)
j@236 63 (format t "Composition added to db, id: ~A~%" composition-id))))
j@236 64
j@236 65
j@236 66 ;;;=====================================================================
j@236 67 ;;; All the below are just helper functions.
j@236 68 ;;;=====================================================================
j@236 69
j@236 70 (defun write-to-db-file (collection-id composition-id composition)
j@236 71 (let ((timebase (midi-timebase composition)))
j@236 72 (with-open-file (stream *import-file*
j@236 73 :direction :output
j@236 74 :if-exists :supersede
j@236 75 :external-format :latin1)
j@236 76 (sequence:dosequence (event composition)
j@236 77 (format stream
j@236 78 "~S ~S \\N ~{~S ~}1~%" ; 1 is the
j@236 79 ; version number
j@236 80 collection-id composition-id
j@236 81 (if (amuse-utils:pitchedp event)
j@236 82 (list (midi-track event)
j@236 83 (midi-channel event)
j@236 84 (midi-patch event)
j@236 85 (midi-pitch-number event)
j@236 86 (midi-velocity event)
j@236 87 (* (timepoint event) timebase)
j@236 88 (* (duration event) timebase))
j@236 89 (list (midi-track event)
j@236 90 (midi-channel event)
j@236 91 0 ;FIXME no patch for perc?
j@236 92 (midi-drum-sound event)
j@236 93 (midi-velocity event)
j@236 94 (* (timepoint event) timebase)
j@236 95 (* (duration event) timebase)))))))
j@236 96 t)
j@236 97
j@236 98 ;;; FIXME: use macros here.
j@236 99
j@236 100 (defun %add-tempo-constituents (collection-id composition-id tempi timebase
j@236 101 database)
j@236 102 #.(clsql:locally-enable-sql-reader-syntax)
j@236 103 (loop ;with constituent-id
j@236 104 for tempo in tempi
j@236 105 do (clsql:insert-records :into "midi_db_tempi"
j@236 106 :attributes '([collection-id]
j@236 107 [composition-id]
j@236 108 [start]
j@236 109 [duration]
j@236 110 [microsecs-per-crotchet])
j@236 111 :values (list collection-id
j@236 112 composition-id
j@236 113 (* (timepoint tempo) timebase)
j@236 114 (* (duration tempo) timebase)
j@236 115 (microseconds-per-crotchet
j@236 116 tempo))
j@236 117 :database database))
j@236 118 #.(clsql:locally-disable-sql-reader-syntax))
j@236 119
j@236 120 (defun %add-timesig-constituents (collection-id composition-id timesigs
j@236 121 timebase database)
j@236 122 #.(clsql:locally-enable-sql-reader-syntax)
j@236 123 (loop for timesig in timesigs
j@236 124 do (clsql:insert-records :into "midi_db_timesigs"
j@236 125 :attributes '([collection-id]
j@236 126 [composition-id]
j@236 127 [start]
j@236 128 [duration]
j@236 129 [numerator]
j@236 130 [denominator])
j@236 131 :values (list collection-id
j@236 132 composition-id
j@236 133 (* (timepoint timesig) timebase)
j@236 134 (* (duration timesig) timebase)
j@236 135 (time-signature-numerator
j@236 136 timesig)
j@236 137 (time-signature-denominator
j@236 138 timesig))
j@236 139 :database database))
j@236 140 #.(clsql:locally-disable-sql-reader-syntax))
j@236 141
j@236 142 (defun %add-keysig-constituents (collection-id composition-id keysigs
j@236 143 timebase database)
j@236 144 #.(clsql:locally-enable-sql-reader-syntax)
j@236 145 (loop for keysig in keysigs
j@236 146 do (clsql:insert-records :into "midi_db_keysigs"
j@236 147 :attributes '([collection-id]
j@236 148 [composition-id]
j@236 149 [start]
j@236 150 [duration]
j@236 151 [mode]
j@236 152 [sharp-count])
j@236 153 :values (list collection-id
j@236 154 composition-id
j@236 155 (* (timepoint keysig) timebase)
j@236 156 (* (duration keysig) timebase)
j@236 157 (key-signature-mode
j@236 158 keysig)
j@236 159 (key-signature-sharps
j@236 160 keysig))
j@236 161 :database database))
j@236 162 #.(clsql:locally-disable-sql-reader-syntax))