File: TODO

package info (click to toggle)
buzztrax 0.10.2-10
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 19,984 kB
  • sloc: ansic: 109,707; sh: 12,875; cpp: 10,882; xml: 6,081; makefile: 508; javascript: 338; asm: 116
file content (468 lines) | stat: -rw-r--r-- 21,013 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
* when releasing do:
  * make check
  * cd po;intltool-update -M
  * make dist
  * wget http://www.gnu.org/licenses/lgpl-2.1.txt; mv lgpl-2.1.txt COPYING; 


* test infrastructure
  * add a stub song-io saver
  * add a stub processor machine
  * have a means to make a copy of log-files for passing tests
    * this could help to check 'what changed'
    * we'd need to also do xml output from check to run the log compare for
      failed tests
  * use https://github.com/martinpitt/umockdev for btic tests


* review tests
  * ensure we follow Arrange/Act/assert or Given/When/Then style
    http://en.wikipedia.org/wiki/Behavior_Driven_Development
  * check that all public api is used in tests
    nm --defined-only .libs/libbuzztrax-core.a | grep " T " | cut -d' ' -f3 | grep -v "marshal" | sort >/tmp/m1.txt;
    nm --undefined-only .libs/libbtcore-check.a | grep " U bt" | cut -c20- | sort | uniq >/tmp/m2.txt;
    comm -2 -3 /tmp/m{1,2}.txt
    
    grep ");" src/lib/core/core.h | cut -d'(' -f1 | cut -d' ' -f2 | cut -d'*' -f2
    find src/lib/core -name "*.h" -exec grep ");" {} \; | cut -d'(' -f1 | cut -d' ' -f2 | cut -d'*' -f2

  * check that we use loop-tests
    find tests/lib/ -name "*.c" -exec egrep -Hn "(for|while)\s*\(" {} \; | egrep -v "(:\s*\*|://)"


* quality checks
  for file in src/lib/core/*.c; do gtkdoc-depscan -v --book gstreamer-1.0:1.2.0 $file; done


* sparse
  make CC=cgcc


* build with clang
  export CC=/usr/bin/clang; export CXX=/usr/bin/clang++; ./autoregen.sh


* generate a dependency matrix
  * 'make ctags' creates tags files per directory containing symbol locations
  * 'ctags -x --recurse src tests >xref' creates a single xref table containing
    all symbol locations
  * 'find . -name "*.o" -exec nm --undefined-only {} \; | grep " bt_"'
    creates a list of externally called entries


= feature =

* controller api
- we might want to allow to attach a controller to a parameter and control
  the controllers parameters in the pattern instead, e.g.:
  - user attaches LFO to Filter-CutOff, in the pattern he can now edit:
    center-value, depth, shape, freq (controlable values of the control-source)
  - user attaches an Arpeggiator to a Note property
- we setup extra controller-functions to scale and shift the value (or
  introduce a special binding for that)
- we need a controlbinding-router so that on pattern basis we can select which
  controlsource is used (pattern, lfo, arpeggiator)
- song format
  - we store it per pattern before the data
- ui
  - we need some extra buttons in the parameter header to select between
    {manual,automation}


* OSC support
  * settings
    - the OSC port for listening
    - add song to path (/<song>/...)
  * namespace
    - ../<machine>/set_{wire,global,voice}_param 
    - ../<machine>/set_{mute,solo,bypass}
    - ../<machine>/<pattern>/set_{wire,global,voice}_event
    - ../{play,stop,pause}
  * ui (if osc enabled)
    - show the osc path both in machine and pattern view
    - eventually make it editable (ensure unique)
    - store with song

  * we can also expose osc as a 'device' in the btic
    - it will support the learn-iface
    - learning will echo all received controls
    - one can then name it and store
    - it would be nice to somehow bundle learned controls as a 'device'
      - then we can have presets per app
      - we could have a "new osc device" menu item in the control menu
        and put the learn item under the new device

  * nice client for android: control
    http://charlie-roberts.com/Control/?page_id=19
    * we can push custom surfaces via osc
      http://charlie-roberts.com/Control/?page_id=32
    * can be discovered via avahi:
      > avahi-browse -a
      +  wlan0 IPv4 Control_75846                                 _osc._udp            local
      +  wlan0 IPv4 Control_66257                                 _osc._udp            local


* undo/redo/journaling
  - links
    http://www.buzztrax.org/index.php/Undo,_redo
    http://www.buzztrax.org/index.php/Song_autosaving
  - we do that on the ui level (also the journalling and the replay of it)
  - singleton journal object
    - each undo/redo capabale object registeres with its name there
    - on replay we can take the prefix og the entry and dispatch
    - on journalling we can probably add the prefix
    - it is a stack of journal entries
  - classes that implement unod/redo implement the change_logger_interface()
    and usually have a BtChangeLog reference in their instance struct
  - pending parts that need undo/redo
    - machine view
      - machine/wire parameters
    - wavetable view
    - info view
  - order of serialisation and destruction
    - see main-page-machines.c:bt_main_page_machines_delete_machine()
    - use g_signal_connect_after() for the '-removed' handler that are
      destructive (search for '-removed",G_CALLBACK') can help
    - g_object_add_weak_ref is not useful as the object is already gone
    - example: bt_setup_remove_machine
      - what we want:
        machine data {
          track data
          pattern data 0
          ...
          pattern data n
        }
      - what happens:
        emit "removed" signal
          pre:
            main-page-machines:on_machine_removed: beg log undo/redo + machine-data
            main-page-sequence:on_machine_removed: track data + remove track
          default: bt_setup_on_machine_removed ?
            foreach pattern do: bt_machine_remove_pattern
              emit "removed" signal
                pre:
                  main-page-patterns:on_pattern_removed: beg log undo/redo + pattern data
                  main-page-sequence:on_pattern_removed: no track -> skip
                default: bt_machine_on_pattern_removed ?
                  -
                after:
                  end log undo/redo
              remove & unref
          after:
            end log undo/redo
        remove & unref
    - generic phases:
      1) owner:before_xxx_removed: beg log undo/redo + xxx data
      2) others:on_xxx_removed: log other object
      3) children: emit 'removed'
      4) owner: after_xxx_removed: end log undo/redo
      5) remove & unref
    - one problem is that objects that gets removed have children and are part of
      other objects:
      - machine has patterns and
      - sequence has tracks that reference machines
    - it is probably easier to have explicit api in the participating UI object
      - we should split functions like:
        void bt_main_page_machines_delete_machine (const BtMainPageMachines * self, BtMachine * machine)
        void bt_main_page_machines_delete_wire (const BtMainPageMachines * self, BtWire * wire)
        to serialize and to actually delete afterwards, this way we can trigger
        the deletion of the top-level after serialisation is done 
      - examples:
        bt_main_page_machines_delete_machine(self, machine) {
          bt_main_page_machines_serialize_machine(self, machine) {
            // 1) serialize own data (properties)
            // 2) serialize data from object that have a ref to this machine by
            g_signal_emit(BtMainPageMachines::machine-delete-event, machine);
              // bt_main_page_sequence_on_machine_delete_event() -> bt_main_page_sequence_delete_track()
            // 3) serialize all children
            foreach(pattern) { bt_main_page_patterns_serialize(self,pattern); } 
          }
          bt_setup_remove_machine(setup, machine);
        }
        bt_main_page_machines_delete_wire(self, wire) {
          bt_main_page_machines_serialize_wire(self, wire) {
            // 1) serialize own data (properties)
            // 2) serialize data from object that have a ref to this wire by
            g_signal_emit(BtMainPageMachines::wire-delete-event, wire);
            // 3) serialize all children
            foreach(pattern) { bt_main_page_patterns_serialize_value_group(self,pattern,wire_value_group); }              
          }
          bt_setup_remove_wire(setup, wire);
        }
        bt_main_page_patterns_delete_pattern() {
          bt_main_page_patterns_serialize_pattern(self, pattern) {
            // 1) serialize own data (properties, value-groups)
            foreach(value-group) bt_main_page_patterns_serialize_value_group(self, pattern, value-group)
            // 2) serialize data from object that have a ref to this pattern by
            g_signal_emit(BtMainPagePatterns::pattern-delete-event, pattern);
              // bt_main_page_sequence_on_pattern_delete_event() -> serialize tracks data for this pattern
            // 3) serialize all children
            // - no children -
          }
          bt_machine_remove_pattern(machine, pattern);
        }
        bt_main_page_sequence_delete_track(self, sequence, track_id) {
          // no refs, no children
        }
        bt_main_page_waves_delete_wave() {
          bt_main_page_waves_serialize_wave(self, wave) {
            // 1) serialize own data (properties)
            // 2) serialize data from object that have a ref to this wave by
            // TODO: we probably don't want this, as we won't clear wave-refs in
            //       pattern when e.g. loading a new wave into an existing slot
            g_signal_emit(BtMainPagePatterns::wave-delete-event, wave);            
            // 3) serialize all children
            // - no children -
          }
          bt_wavetable_remove_wave(wavetable, wave);
        }


* Hide libxml2 use behind a PersistenceIO interface in a XMLPersistenceIO
  implementation. The API would also allow to change the implementation to use
  e.g. json or a binary representation instead. We need an API like:
  PersistenceIONode: opaque handle
  // for saving
  PersistenceIONode *bt_persistence_io_new_node(PersistenceIONode *parent, gchar *name);
  gboolean bt_persistence_io_set_value(PersistenceIONode *parent, gchar *value);
  gboolean bt_persistence_io_set_attribute(PersistenceIONode *parent, gchar *name, gchar *value);
  // a varargs function that takes (gchar *name, GType type, <type> value)
  // triplets, terminated by NULL 
  gboolean bt_persistence_io_set_attributes(PersistenceIONode *parent, 
    gchar *name, ...);
  // collection api ...
  gboolean bt_persistence_io_set_attributes_from_hash_table(PersistenceIONode *parent, GHashTable *hash_table);
  
  // for loading
  GList *bt_persistence_io_get_nodes(PersistenceIONode *parent);
  gchar *bt_persistence_io_get_value(PersistenceIONode *parent);
  gchar *bt_persistence_io_get_attribute(PersistenceIONode *parent, gchar *name);
  // a varargs function that takes (gchar *name, GType type, <type *> value)
  // triplets, terminated by NULL 
  gboolean bt_persistence_io_get_attributes(PersistenceIONode *parent, 
    gchar *name, ...);


* CPU load per machine
  - as we always plug the tee-elements on each machine and each wire starts with
    a queue we could do CPU load per thread
    - sources start their own thread
    - effects and the sink live in the thread of one of the incoming wires
    - build a thread_id<->machine mapping
      - a hackish way would be to run a pad_probe before the machine and
        send a message to the bus with the thread-id<->machine association
      - a better way would be to use gst_message_parse_stream_status
        see src/lib/core/song.c::on_song_stream_status()
  - ideally we show it on the machine view
    - extra dialog from tools menu?
    - enable/disable from the view menu
  - buzztrax-cmd could have a profile option (for play/encode) and print a summary
    at the end


* eventually merge machine-rename dialog with machine properties
  - we now have inplace rename in the sequence headers as a quick alternative


* control machines (no in/out)
  - color=gray
    it is never connected and thus, does not need a desaturated shade
  - scheduling
    - from a property notifies on sink-bin
      - need ts
    - run a GstTask and sync to the clock
      - need to implement tempo iface
      - need to hande seeks (to know direction :/)
  - we can use that for midi-out
    - global params: midi-device (enum)
    - voice params: midi-channel, note, velocity, controller1, control-value1, ... 
  - subclass the control-machines from GstElement
    - no pads (and therefore no _loop() or _chain() function
    - we see them in the registry


* change presets via controller
  * for midi we can expose program change message
    * although our presents don't have stable ordering
    * a rel-range control? (prev/next)
  * we need a way in the ui to attach such a controller to the preset pane


* play machines via midi (interaction controller)
  - we have machines with one or more note-params
    - sometimes only one is a trigger though
    cd bml/tests/testmachine
    grep -H PT_NOTE *.txt.* | sort | uniq -c | sort -g
  - we have machines with one or more value trigger parames (drum machines)
  - we need to have the idle_loop playing when having keyboard assignments
  - gui workflow:
    - v1: start from the key-controllers
      - a toolbar on the bottom
        - show/hide in the view menu
        - left a combobox to select the device (keyboard, midi, ...)
        - next the piano key graphics
        - next two comboboxes for key assignment and velocity assignment
          - velocity assignment is empty, when selecting machine+key,
            it will show possible velocity targets
          - for drum-machines, we select the parameter with the key and put the
            velecity into the respective parameter
      - mark a key-range, assign to machine/note-param (with key offset)
      - select a key-range, unassign
      - move key-ranges
    - v2: start from pattern column headings
      - have bind/unbind like in machine window
      - define split'ed devices elsewhere
    - v3: add controller to context menu on machine-canvas 
  - how to easily assign a series of key to a series of triggers in one machine
    - have a trigger group  (and assign to white keys only)
    - this would manage both key-number and velocity as we'd only bind a series
      of abs-value-controls (velocity) to the drum-machine triggers
  - how to assign velocity to the machines velocity param
    - it works for monophonic machines
  - poly key-press events
    - the current code in machine.c (_poly_control_) would increment the
      voice_ct on each control event
      - we would need to set both key and velocity though
      - we also need to ensure to set velocity first and then the key
      - each controller has a separate voice_ct
      - when assinging a controller to a voice-param, should we always poly-bind
        it?

  - it would be nice to have a pc-keys interaction controller for playing notes
    - we can register this from the ui (it would be part of "ui/edit"
      - the machine view would start-stop it on focus (if bound)
      - eventually we could use it in pattern-view too and implicitely bind it
        if "play-notes" is active


* text parameters in machines
  * for a:
    * text to speech machine we'd like to have strings in the pattern
    * cmd-out machine we'd like to send a dbus command, run a script etc.
  * like we have a wavetable, we could have a text table
    * a list of text snipped (more than 256!)
    * each snippet has a label and a text block (multiline)
  * in a text to speech machine we can use text-table index (gint 16 bit),
    text offset (gint 16 bit char offset), length (unset, to the end) and
    direction (forward, backward)
  * in a command out machine, we use the text table index (gint 16 bit) and
    ev. script parameters (passed as $1, $2, ...)


* wave table
  * we can just keep the buffers from fakesink/appsink in a list and consolidate
    on eos
  * record audio
    * need device selection on the source
  * record from song
    * need some special setup on sink-bin/encodebin
    * load raw wave on song::playing==FALSE


* one framerate for animations
  * we have a couple of things that we update in intervals:
    * 10fps: main-page-waves.c: preview_update_id=g_timeout_add_full(G_PRIORITY_HIGH,1000/10,on_preview_playback_update,(gpointer)self,NULL);
    * 10fps: main-toolbar.c: playback_update_id=g_timeout_add_full(G_PRIORITY_HIGH,1000/10,on_song_playback_update,(gpointer)song,NULL);
    * 10fps: machine.c: g_object_set(PART_*LEVEL,"interval",(GstClockTime)(0.1*GST_SECOND),...
    * 10fps: signal-analysis-dialog: g_object_set(ANALYZER_*, "interval",(GstClockTime)(0.1*GST_SECOND),...
  * we should have one #define somewhere for the UPDATE_INTERVAL
  * ideally we ensure that the framerate is an integer multiple of it
  * it would be nice to avoid a setting, but for slow machines it might be worth it
    (or for fast machine, people could pick a higher rate)
  * we could use configure and have the define in config.h


* pattern and main-page-patterns still contain bits of duplicated code
  * review the pattern api and check if we should use the groups directly
    (run ./api-cleanup.sh to get a report of where the api is used)


* create & add is a bad idea
  * machines and wires are automatically added to the setup
  * patterns are automatically added to the machine
  * this causes trouble for pattern_copy (which we work-around now)


* change tempo while playing
  * we would like to ensure that playback continues at the same position, just
    at different speed
  * when changing the tempo, we'd need to take a snapshot of the playback pos as
    time and ticks


* embedded lua (see design/lua) or js (see design/{gjs,seed})
  * tools menu
  * pattern editor
    * register scripts that provide commands to manipulate the patterns
    * the app does undo/redo, but comparing the before after state
    * script will needs to provide a name
    * if we have a keybinding editor, we can associate the function with the key
      there
    * we could also have an eval entry in the editor, that would fill a selection
      with result of cell(tick) = map(f(tick)). tick could either be the absolute
      tick or 0.0 ... 1,0 and map will project the function return from 0.0 ... 1.0
      to the value vange of the selected property
  * interaction controller ?
  * do we need to store some of them with the song?


* machine UIs
  * instead of adding more metadata to the paramspecs we could also use 
    GtkBuilder xml file. This way machines can ship a customized layout.
  * if not present in the filesystem we generate them on
    the fly, maybe also expose this as a standalone tool
  * the xml file only covers the parameter boxes


* single window UI
  * like we have main-window.c, add a extra-window.c, where the extra window
    only has a main-pages widget
  * on each tab we have a context menu to move it to the 'next'/'prev' window
  * each page is only part of one window
  * the settings store how many extra windows we have and for each page in which
    one it is docked
  * when we close an extra window, we move the pages to the previous window
  * the edit-application stores the list of the windows that are open
  * see design/gui/multiscreen.c, when saving the monitor positions
    gdk_screen_get_monitor_at_point()


* physical remotes
  * physical remotes to control synths
  * each synth could generate the required arduino sketch + instructions for the
    hw
  * arduino/esp2866
    * https://www.adafruit.com/products/1085: 4ch @ 16bit: 15$
    * https://www.adafruit.com/products/1083: 4ch @ 12bit: 10$
    * https://www.adafruit.com/products/856:  8ch @ 10bit:  3.75$
    * Arduino Uno: 6ch @ 10bit (mine)
    * Arduino Micro: 12ch @ 10bit
    * Teensy 3.1: 21ch @ 10bit (12ch on the headers)
  * controls
    * trigger button
      https://www.arduino.cc/en/tutorial/button
    * toggle button
      https://www.arduino.cc/en/Tutorial/Switch
    * poti
      https://www.arduino.cc/en/Tutorial/AnalogInput
    * many buttons on 1 ADC pin
      http://www.instructables.com/id/How-to-access-5-buttons-through-1-Arduino-input/?ALLSTEPS
      useful also for rotary switches like e.g.
      https://www.sparkfun.com/products/10064?_ga=1.108337922.1878275335.1438803671
      http://www.conrad.de/ce/de/Search.html?search=Encoder+5+V%2FDC+0.01+A+Schaltpositionen+16&searchType=mainSearchBar
      e.g. for mode-selectors
  * send osc events
    http://trippylighting.com/2014/10/12/touchosc-arduino-tutorial/


* internet exchange for ic-profiles
  * store ic-profiles also on files.buzztrax.org/ic-profiles
  * when plugging a ic-device, check if we find a profile online
  * from the profile-settings, add a button to submit a profile
    * ideally upload through a the mailing-list/wordpress/...
    * if we upload to files.buzztrax.org, upload to a staging area, where the uploads
      are limited by ip/size/... and files are checked immediately after upload
      for the file-type
    * if we upload to wordpress, we'd need to do OAuth2 to avoid storing the
      password in the settings
  * maybe do something similar for presets