sync-server-receive   scheme


Defined in:  https://github.com/digego/extempore/tree/v0.8.9/libs/core/toplap_clock.xtm

Implementation

(define sync-server-receive
  (lambda (timestamp address srcip srcport . args)
    (cond ((string=? address "/clock/election/q")
           ;; someone has asked for an election!
           ;; if we have a higher election-val OR we are allready the master
           ;; then send a message back, otherwise don't!
           (let ((election-val (car args)))
             (if (or *master*
                     (> *election-val* election-val))
                 (io:osc:send (now) (cons srcip srcport) "/clock/election/r"))))
          ((string=? address "/clock/election/r")
           ;; if we receive an election reply
           ;; then we are definitely NOT the master
           ;; also don't try for re-election again
           ;; for AT LEAST 5 seconds!
           (set! *toplap-lastmsg* (+ 5. (clock:clock)))
           (set! *election-winner* #f))
          ((string=? address "/clock/sync/q")
           ;; if someone asks for a clocksync (from any IP and any PORT)
           ;; and we are the master then send a reply
           ;; first arg is t1 (from client) we add t2 to reply
           (if *master*
               (let ((t (split-clock-time (clock:clock))))
                 (io:osc:send (now) (cons srcip srcport) "/clock/sync/r"
                              (car args) (cadr args)
                              (car t) (cdr t)))))
          ((string=? address "/clock/sync/r")
           ;; clock syncs come from current master
           (let* ((t1 (join-clock-time (car args) (cadr args)))
                  (t2 (join-clock-time (caddr args) (cadddr args)))
                  (t3 t2)
                  (t4 (clock:clock))
                  (msg-delay (- t4 t1))
                  (offset (/ (+ (- t2 t1) (- t3 t4)) 2.0)))
             (set! *toplap-clock-global-offset* offset)
             (set! *masterip* srcip)
             (if (not (string=? *masterip* *oldmasterip*))
                 (begin (ascii-print-color 0 5 9)
                        (println)
                        (println 'There 'is 'a 'new 'toplap 'clock 'in 'town! srcip)
                        (println)
                        (ascii-print-color 0 7 9)
                        (set! *master* #f)
                        (set! *oldmasterip* *masterip*)))
             (set! *toplap-lastmsg* (clock:clock))))
          ((string=? address "/clock/master/q")
           ;; if current master send reponse
           ;; srcport need not be same as *toplap-port*
           (if *master*
               (io:osc:send (now) (cons srcip srcport) "/clock/master/r")))
          ((string=? address "/clock/master/r")
           ;; if we get a message it must be from master
           ;; so we can set the *mastersip* to whatever the srcip is
           (set! *mastersip* srcip)) ;; master port must be *toplap-clock-port*
          ((string=? address "/clock/cycle/set")
           ;; cycle changes are sent to master only (i.e. not broadcast)
           ;; to ensure that we don't have the problem where some
           ;; clients GET the message but the master DOESN'T!
           (if *master*
               (let ((beat-n (car args))
                     (beat-d (cadr args))
                     (cycle (caddr args)))
                 (*metro* 'set-cycle cycle (/ beat-n beat-d))
                 ;; broadcast new bpm details as cycle/update
                 (io:osc:send (now) *toplap-sync-broadcast* "/clock/cycle/update"
                              beat-n beat-d cycle))))
          ((string=? address "/clock/cycle/update")
           (apply io:osc:send (now) *toplap-clock-server* "/clock/cycle/update" args))
          ((string=? address "/clock/bpm/set")
           ;; bpm changes are sent to master only (i.e. not broadcast)
           ;; to ensure that we don't have the problem where some
           ;; clients GET the message but the master DOESN'T!
           (if *master*
               (let ((time (join-clock-time (car args) (cadr args)))
                     (beat-n (caddr args))
                     (beat-d (cadddr args))
                     (bpm (car (cddddr args))))
                 (*metro* 'set-tempo bpm (clock->samples time) (/ beat-n beat-d))
                 ;; broadcast new bpm details as bpm/update
                 (io:osc:send (now) *toplap-sync-broadcast* "/clock/bpm/update"
                              (car args) (cadr args) beat-n beat-d bpm))))
          ((string=? address "/clock/bpm/update")
           (apply io:osc:send (now) *toplap-clock-server* "/clock/bpm/update" args))
          (else (println 'bad 'osc 'message: address)))))


Back to Index