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