-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathTODO
640 lines (574 loc) · 28.9 KB
/
TODO
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
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
* 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
* or use memory based song-io-native-xml:
* add BtSongIO *bt_song_io_to_data(gpointer *data, guint *len, const gchar * media_type); or do we use song-io-native-xml anyway
* saving
* create song1
* save song1 to memory
* load from memory to song2
* compare song1 and song2 - but how - we don't had a compareable iface
* maybe use canolicalized xml (what about waves?)
* loading
* load song1 from memory1
* save song1 to memory2
* compare memory1 & memory2
* if before/after differs we need a nice formatting :/
* dump both songs using xmlDocFormatDump(file, doc, TRUE) and diff
* or test via BtPersistence directly
* or we just have a save & load helper
* we need to verify loading first
* load from memory and check details
* then test saving and assume that loading is good
* 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 need a download script to mirror the logs from travis/s3 bucket
* we have past logs at travis, need some scripts to analyze them
* get suite/test/duration via xmlstarlet:
xmlstarlet sel -t -m "/_:testsuites/_:suite/_:test" -s A:N:- "_:duration" -v "concat(_:duration, ', ', _:fn, ', ', _:id)" -n log.xml
for file in */log.xml; do echo $file; xmlstarlet sel -t -m "/_:testsuites/_:suite/_:test" -s A:N:- "_:duration" -v "concat(_:duration, ', ', _:fn, ', ', _:id)" -n $file | tail -n 3; echo; done
* check for flaky tests
* write a scripts that goes over all the songs under a directory and:
* load + info them
* render them to a set of given formats
* load + save to tmp + compare orig with tmp
* for hand-witten songs, we need to initially fix the delta
* for binary formats
* we cannot really diff
xmllint --c14n11 --format tests/songs/buzz1.xml >/tmp/bt-in.xml
./buzztrax-cmd -c convert -i tests/songs/buzz1.xml -o /tmp/bt-tmp.xml
xmllint --c14n11 --format /tmp/bt-tmp.xml >/tmp/bt-out.xml
diff /tmp/bt-in.xml /tmp/bt-out.xml
* 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 controller's parameters in the pattern/property window instead, e.g.:
- user attaches LFO to Filter-CutOff, the original param expands to:
center-value (original value), depth, shape, freq (controlable values of the
control-source)
- user attaches an Arpeggiator to a Note property, the original param expands
to: note (original, pattern, (speed))
- the arp, ideally needs a chord (or multiple notes), so maybe we have
arp-3 (adds two params for semitone offsets) and arp-4 (adds three params)
- extra controllable parameter on pattern-control-source for transpose
(parameters will be part of the sequence)
- we add a transform-controller that has shift/scale params and takes a value
- neutral is shift=0.0, scale=1.0
- it can have a boolean clamp param
- if we do this per pattern
- we need a controlbinding-router so that on pattern basis we can select which
controlsource is used (pattern, lfo, arpeggiator)
- parameter-group can already deal with different parents for each property,
but we can't change this per pattern
- the pattern layout would be different not only per machine, but also per
pattern
=> so maybe you choose this per song
- file format
- per song
- we store it in the machine before <global,voice>data
- per pattern
- we store it before the tick-data
- format:
<controller name="<property>" type="lfo">
and then in the pattern for the ticks we store
<globaldata name="<property>.<control-property>" value="<val>">
- ui
- we need some extra buttons in the parameter header to select between
{manual,automation} (cant use a context menu here) and in the context menu
of the machine properties window
-
- pros and cons:
- we can't store these setups in presets
(we need a way to make those modulation setup part of presets)
- quite a lot of work (maybe this is overkill and the elements should just do
it them self)
+ this would be a nice way of adding an arpeggiator
+ adds a lot of flexibility and keeps the plugins simple
* editable machines
* polybin
* idea:
* select machine that does not support childbin yet
* internal pipelines:
* source: src[n] | adder
* effect: tee ! effect[n] | adder
* select which properties to expose as global params, other are per voice
* templates
* idea:
* load a song fragment
* show a list of machines with their parameters, ignore master
* select which properties to expose
* issues:
* what if some elements are polyphonic?
* can we wrap a template machine into a polybin?
* ext midi
* idea:
* midi-out + audio-in with latency compensation
* select an audio-in and a midi out
* meassure latency and store with setup
* midi-device program list as presets
* 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
* 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)
* alternatively we can have the text in the machine properties
* 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, ...)
* the machines should implement property meta and implement a describe
function to show the referenced text snippet
* 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
* eventually merge machine-rename dialog with machine properties
- we now have inplace rename in the sequence headers as a quick alternative
- with the parameter-view (as proposed below) we can also rename in the
parameter-view headers
* single window UI + multiscreen support
* for the single window support add a parameter view (F7)
* this will dock all machine-property dialogs (and maybe also machine-
preferences and machine-controls through tabs)
* from sequence/pattern view one can just there with shift+enter
* we need shortcuts to cycle: parameters -> patterns -> sequence
* maybe we just use enter to cycle through the chain (and shift-enter to
cycle backwards if the cycle gets longer)
* TODO: what about the signal-analysis-dialogs?
* another page with them stacked horizontaly?
* like we have main-window.c, add a extra-window.c, where the extra window
only has a main-pages widget
* when opening the new window, try to place it on the next monitor if there
is no space on the current monitor
* maybe also have a way to split a window with a hpaned to allow split on
one monitor
* 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
* preview in generator meachines
* feature
* we'd like to have a preview for what the generator would output
* we'd like this preview to e updated when editing the parameters from the UI
* ways to do this:
* preview interface where one sets a preview buffer
- need to make sure that calling create() does not modify machine state
* run a shadow machine in a preview pipeline connected to a memorysink/fakesink
- need to clone the parameters
+ if polyphonic, can force to one voice
+ does not interfere with normal playback
+ would work for *all* machines
* open questions
* how can we figure how long to make the preview buffer ?
* we have a target size (from the window width)
* we could let the preview pipeline run and store result buffers in a list
until the level drops below a threshold or we reach 1 sec? We then
resample the buffer into the preview array
* we should use a low sampling rate and trigger the first trigger param
(max volume, C-0)
* custom pipeline scheduler
* sadly adder is still racy and audiomixer is lacking features, beside pull
based scheduling is not seeing any improvements either
* we could implement manual scheduling on the top-level pipeline
* key point to keep in mind:
* if we don't use adders we need to mixing ourself
* if we don't use tees we need to refcount outgoing buffers to avoid
recalculating
* seeks go to the sink, new-segments needs to be send from sources after a
seek
* common code changes:
* keep all BtMachine bins in the pipeline but not connect them
* replace adder/tees with fakesrc/sink or appsrc/sink
* the ghostpads get a pad-probe (or we use the respective callbacks)
* push based scheduling idea:
* sort the BtMachines topologically starting from sources into a list
* level is max(depth) from sources
* when playing, gstreamer will call create on all sources
* we let native sources create, but block fakesource until all predecessor
elemets have buffers, once that is true, we mix and send
* pull based scheduling idea:
* confige everything for pull (we need to test that the BtMachines itself
would work in pull mode)
* sort the BtMachines topologically starting from the sink into a list,
where each BtMachine knows its predecessors and has a count of successors
* level is max(depths) from sink
* maintain a pool of buffer (upper size is number of machines)
* when playing, gstreamer will pull on the BtSiinkMachine and when the
PadProbe is triggered with a buffer, we
* build a list of buffers from the one we got plus buffers from the pool
* loop over the predecessors elements
* if buffer-ptr=null take a buffer from the list, assign, set ref_ct to
num_sucessors and pull on the sink ghostpad and return the buffer
* else return the existing buffer
* when returning the buffer dec the ref_ct and once 0 return the buffer
to the pool
* once they all return mix into the 1st buffer we got from the probe
* TODO:
* make a standalone toy that can validate the graph mandling?
* test what happens with events if we have all these parallel sub pipelines
(each BtMachine will have sinks and sources now). The GstPipeline will
probably send seek-events to each pipeline (which is probably okay)