-
Notifications
You must be signed in to change notification settings - Fork 1
Extending sol
this section describes sol's structure and how to extend sol
database
^ |
| v
inputs -> control -> gui
(magi) <-
| ^
v |
model
-
control aka MAGI
- the brains
- gets input from
- inputs - midi or osc
- its own state (for example, when to loop)
- the gui
-
database
- the data
- abstractions of clips
- collections to store clips
- methods to update or query database
- save/load
-
gui
- what's happening right now
- what can be changed
- multiple views
- performance
- library organization
- clip collection organization
-
models
- provide compatible api(s)
- translates info coming in so that it can go out
magi controls everything, instead of writing out everything i will list the osc addresses magi uses. note that anywhere you see {}, that means each layer is assigned its own address eg /magi/layer0/playback/play would play on layer 0.
inputs/outputs that are model specific are specified within the model ie addresses for current clip positions or playback control.
| address | description |
|---|---|
| - | timeline control |
| /magi/control{}/start | start control |
| /magi/control{}/stop | stop control |
| /magi/control{}/do | do control |
| /magi/control{}/sens | modify control sensitivity |
| /magi/fft/control{} | fft control |
| - | playback control |
| /magi/layer{}/playback/play | play |
| /magi/layer{}/playback/pause | pause |
| /magi/layer{}/playback/reverse | reverse |
| /magi/layer{}/playback/random | random |
| /magi/layer{}/playback/seek | seek |
| /magi/layer{}/playback/clear | clear |
| /magi/layer{}/playback/speed | speed |
| /magi/layer{}/playback/speed/adjust | adjust speed |
| /magi/layer{}/playback/speed/adjust/factor | adjust speed by a factor |
| - | clip control |
| /magi/layer{}/cue | set/activate cue point |
| /magi/layer{}/cue/clear | clear cue point |
| /magi/layer{}/loop/on_off | de/activate looping |
| /magi/layer{}/loop/type | change loop type |
| /magi/layer{}/loop/select | select loop range |
| /magi/layer{}/loop/select/move | select a loop range relatively |
| /magi/layer{}/loop/set/ | set the loop range |
| /magi/layer{}/loop/set/a | set the loop range's beginning |
| /magi/layer{}/loop/set/b | set the loop range's end |
| /magi/layer{}/loop/set/ab | set both beginning and end |
| /magi/layer{}/loop/set/cur/a | set the beginning to current position |
| /magi/layer{}/loop/set/cur/b | set the end to currrent position |
| /magi/layer{}/loop/clear | reset the loop range |
| - | clip collection manipulation |
| /magi/cur_col/select_clip/layer{} | select a clip from current collection |
| /magi/cur_col/add | add a collection |
| /magi/cur_col/delete | delete a collection |
| /magi/cur_col/select | select a collection |
| /magi/cur_col/select_left | select collection to the left |
| /magi/cur_col/select_right | select collection to the right |
| /magi/cur_col/swap | swap collections |
| /magi/cur_col/swap_left | swap left |
| /magi/cur_col/swap_right | swap right |
| - | search |
| /magi/search | perform a search |
| /magi/search/select/layer{} | select a search result |
| - | midi / associated gui things |
| /midi | used for midi control |
| /magi/gui/layer{}/qp_lp_toggle | toggle whether pads affect qp or lp |
| /magi/gui/layer{}/pads_toggle | toggle whether pads activate or delete on press |
| /magi/gui/layer{}/pad/activate | activate pad |
| /magi/gui/layer{}/pad/deactivate | deactivate pad |
| /magi/gui/layer{}/pad_press | press pad (depends on state of pads_toggle) |
| /magi/gui/layer{}/pad/press_qp | press qp pad |
| /magi/gui/layer{}/pad/press_lp | press lp pad |
the database contains all information about clips including parameters, cue points, loop points, last playback state, etc.
if you want to modify this, you can always add more params
within the database submodule are methods for searching, saving/loading savedata, thumbnail generation etc.
to write your own gui create a new class and pass magi the gui as follows
from sol import Magi
magi = Magi()
magi.gui = MyCoolGui(magi)
magi.start()a gui that you pass to magi directly requires the following functions to be implemented
def update_clip(self,layer,clip):
""" update a layer with new clip. or if clip is none clear it """
def update_clip_params(self,layer,clip,param):
""" dispatch a new clip parameter """
def update_cur_pos(self,layer,pos):
""" update current playback position for a layer """
def update_search(self):
""" do something when a search has occured """
def update_cols(self,what,ij=None):
""" update clip collections
what - select, add, remove, swap
ij - what index (swap uses a tuple..) """
def update_clip_names(self):
""" clip names have changed """
def update_gui_directly(self, layer, what, n=-1):
""" added for midi control
what - qp_lp_toggle, pads_toggle, pad_activate, pad_deactivate, pad_press, qp_pad_press, lp_pad_press
n - what index (optional) """sol_mt works like any other gui except it sends some extra information to a potentially external client.
if you wish to write your own client, you need to send the correct osc commands to magi as above
a sol_mt client will receive messages at the following addresses
| address | description |
|---|---|
| /modvj/sol_mt/layer{}/cur_pos | current clip position |
| /modvj/sol_mt/layer{}/cur_col_clip_i | index of current clip within clip collection |
| /modvj/sol_mt/layer{}/qp | cue points status |
| /modvj/sol_mt/layer{}/loop/cur_range | loop current range |
| /modvj/sol_mt/layer{}/loop/on_off | loop status |
| /modvj/sol_mt/layer{}/loop/type | loop type |
| /modvj/sol_mt/layer{}/loop/lp | loop ranges |
| /modvj/sol_mt/layer{}/loop/lp_i | index of loop selection |
| /modvj/sol_mt/layer{}/spd | playback speed |
| /modvj/sol_mt/layer{}/sens | control sensitivity |
| /modvj/sol_mt/update_thumbs | update clip thumbnails |
the tricky points are:
-
/qpand/lpwill send comma separated lists of whether or not a cue point/loop range is set per bucket -
/update_thumbswill send a comma separated list of thumbnail numbers, it's up to you to generate these thumbnails by runningsol_mt -gand copying the files to a place where your client can read them.
each model specifies input/output osc addresses for external players.
each model needs to have the following fields
self.clip_pos_addr[n] # addresses for each layer where the player will send current clip position to
self.external_looping # true or false, whether you want to use the external player's looping functionalityand the following functions
play
pause
reverse
random
set_clip_pos
select_clip
clear_clip
set_playback_speed
# only if self.external_looping is True
set_loop_a
set_loop_b
set_loop_type