FoxDot.lib.TempoClock

Clock management for scheduling notes and functions. Anything ‘callable’, such as a function or instance with a __call__ method, can be scheduled. An instance of TempoClock is created when FoxDot started up called Clock, which is used by Player instances to schedule musical events.

The TempoClock is also responsible for sending the osc messages to SuperCollider. It contains a queue of event blocks, instances of the QueueBlock class, which themselves contain queue items, instances of the QueueObj class, which themseles contain the actual object or function to be called. The TempoClock is continually running and checks if any queue block should be activated. A queue block has a “beat” value for which its contents should be activated. To make sure that events happen on time, the TempoClock will begin processing the contents 0.25 seconds before it is actually meant to happen in case there is a large amount to process. When a queue block is activated, a new thread is created to process all of the callable objects it contains. If it calls a Player object, the queue block keeps track of the OSC messages generated until all Player objects in the block have been called. At this point the thread is told to sleep until the remainder of the 0.25 seconds has passed. This value is stored in Clock.latency and is adjustable. If you find that there is a noticeable jitter between events, i.e. irregular beat lengths, you can increase the latency by simply evaluating the following in FoxDot:

Clock.latency = 0.5

To stop the clock from scheduling further events, use the Clock.clear() method, which is bound to the shortcut key, Ctrl+.. You can schedule non-player objects in the clock by using Clock.schedule(func, beat, args, kwargs). By default beat is set to the next bar in the clock, but you use Clock.now() + n or Clock.next_bar() + n to schedule a function in the future at a specific time.

To change the tempo of the clock, just set the bpm attribute using Clock.bpm=val. The change in tempo will occur at the start of the next bar so be careful if you schedule this action within a function like this:

def myFunc():

print(“bpm change!”) Clock.bpm+=50

This will print the string “bpm change” at the next bar and change the bpm value at the start of the following bar. The reason for this is to make it easier for calculating currently clock times when using a TimeVar instance (See docs on TimeVar.py) as a tempo.

You can change the clock’s time signature as you would change the tempo by setting the meter attribute to a tuple with two values. So for 3/4 time you would use the follwing code:

Clock.meter = (3,4)

class FoxDot.lib.TempoClock.History[source]

Bases: object

Stores osc messages send from the TempoClock so that if the Clock is reveresed we can just send the osc messages already sent

add(beat, osc_messages)[source]
class FoxDot.lib.TempoClock.Queue(parent)[source]

Bases: object

add(item, beat, args=(), kwargs={}, is_priority=False)[source]

Adds a callable object to the queue at a specified beat, args and kwargs for the callable object must be in a list and dict.

after_next_event(beat)[source]
before_next_event(beat)[source]
clear()[source]
get_clock()[source]
get_server()[source]

Returns the ServerManager instanced used by this block’s parent clock

next()[source]
pop()[source]
class FoxDot.lib.TempoClock.QueueBlock(parent, obj, t, args=(), kwargs={}, is_priority=False)[source]

Bases: object

add(obj, args=(), kwargs={}, is_priority=False)[source]

Adds a callable object to the QueueBlock

all_items()[source]
append_osc_message(message)[source]

Adds an OSC bundle if the timetag is not in the past

objects()[source]
players()[source]
priority_levels = [<function QueueBlock.<lambda>>, <function QueueBlock.<lambda>>, <function QueueBlock.<lambda>>, <function QueueBlock.<lambda>>]
send_osc_messages()[source]

Sends all compiled osc messages to the SuperCollider server

classmethod set_server(server)[source]
start_server(serv)[source]
class FoxDot.lib.TempoClock.QueueObj(obj, args=(), kwargs={})[source]

Bases: object

Class representing each item in a QueueBlock instance

exception FoxDot.lib.TempoClock.ScheduleError(item)[source]

Bases: Exception

class FoxDot.lib.TempoClock.SoloPlayer[source]

Bases: object

SoloPlayer objects

active()[source]

Returns true if self.data is not empty

add(player)[source]
reset()[source]
set(player)[source]
class FoxDot.lib.TempoClock.TempoClock(bpm=120.0, meter=(4, 4))[source]

Bases: object

classmethod add_method(func)[source]
bar_length()[source]

Returns the length of a bar in terms of beats

bars(n=1)[source]

Returns the number of beats in ‘n’ bars

beat_dur(n=1)[source]

Returns the length of n beats in seconds

beats_to_seconds(beats)[source]
calculate_nudge(time1, time2, latency)[source]

Approximates the nudge value of this TempoClock based on the machine time.time() value from another machine and the latency between them

call(obj, dur, args=())[source]

Returns a ‘schedulable’ wrapper for any callable object

clear()[source]

Remove players from clock

connect(ip_address, port=57999)[source]
debug(on=True)[source]

Toggles debugging information printing to console

every(n, cmd, args=())[source]
flag_wait_for_sync(value)[source]
future(dur, obj, args=(), kwargs={})[source]

Add a player / event to the queue dur beats in the future

get_bpm()[source]

Returns the current beats per minute as a floating point number

get_elapsed_beats_from_last_bpm_change()[source]

Returns the number of beats that should have elapsed since the last tempo change

get_elapsed_seconds_from_last_bpm_change()[source]

Returns the time since the last change in bpm

get_latency()[source]

Returns self.latency (which is in seconds) as a fraction of a beat

get_sync_info()[source]

Returns information for synchronisation across multiple FoxDot instances. To be stored as a JSON object with a “sync” header

get_time()[source]

Returns current machine clock time with nudges values added

get_time_at_beat(beat)[source]

Returns the time that the local computer’s clock will be at ‘beat’ value

json_bpm()[source]

Returns the bpm in a data type that can be sent over json

kill_tempo_client()[source]
kill_tempo_server()[source]

Kills the tempo server

mod(beat, t=0)[source]

Returns the next time at which Clock.now() % beat will equal t

next_bar()[source]

Returns the beat value for the start of the next bar

next_event()[source]

Returns the beat index for the next event to be called

now()[source]

Returns the total elapsed time (in beats as opposed to seconds)

osc_message_time()[source]

Returns the true time that an osc message should be run i.e. now + latency

players(ex=[])[source]
reset()[source]

Deprecated

run()[source]

Main loop

schedule(callable, beat=None)[source]

Add a player / event to the queue

seconds_to_beats(seconds)[source]

Returns the number of beats that occur in a time period

server = FoxDot ServerManager Instance -> localhost:57110
set_cpu_usage(value)[source]

Sets the sleep_time attribute to values based on desired high/low/medium cpu usage

set_latency(value)[source]

Sets the latency attribute to values based on desired high/low/medium latency

classmethod set_server(server)[source]

Sets the destination for OSC messages being compiled (the server is also the class that compiles them) via objects in the clock. Should be an instance of ServerManager - see ServerManager.py for more.

set_tempo(bpm, override=False)[source]

Short-hand for update_tempo and update_tempo_now

set_time(beat)[source]

Set the clock time to ‘beat’ and update players in the clock

shift(n)[source]

Offset the clock time

start()[source]

Starts the clock thread

start_tempo_server(serv, **kwargs)[source]

Starts listening for FoxDot clients connecting over a network. This uses a TempoClient instance from ServerManager.py

stop()[source]
swing(amount=0.1)[source]

Sets the nudge attribute to var([0, amount * (self.bpm / 120)],1/2)

sync_to_espgrid(host='localhost', port=5510)[source]

Connects to an EspGrid instance

sync_to_midi(port=0, sync=True)[source]

If there is an available midi-in device sending MIDI Clock messages, this attempts to follow the tempo of the device. Requies rtmidi

tempo_client = None
tempo_server = None
update_network_tempo(bpm, start_beat, start_time)[source]

Updates connected FoxDot instances (client or servers) tempi

update_tempo(bpm)[source]

Schedules the bpm change at the next bar, returns the beat and start time of the next change

update_tempo_from_connection(bpm, bpm_start_beat, bpm_start_time, schedule_now=False)[source]

Sets the bpm externally from another connected instance of FoxDot

update_tempo_now(bpm)[source]

emergency override for updating tempo

waiting_for_sync = False
class FoxDot.lib.TempoClock.Wrapper(metro, obj, dur, args=())[source]

Bases: LiveObject