Page 1 of 1

clip "playing_status" using the bang message in JavaScript

Posted: Sat Jan 15, 2011 10:17 pm
by DirectGumby
Hello all,

Let me start with what I am trying to do:
1) Figure out if a clip and clip_slot playing_status
2) Figure out if the clip is:
a) is_recording
b) is_playing
3) I would like to do this all from listeners inside of JavaScript

Why do I want to do this inside of JavaScript?
In short I've build a nice set of recursive functions that goes through all of my UI and sets up listners for all of the objects and properties I care about. In this case I'd like to be albe to handle the bang message and update my state in JavaScript to the correct playing_status, is_playing, and is_recording.

Note: I have all other data types updating properly, I'm just not sure how to use the bang object in JS.

Any help here would be greatly appreciated.

Thanks,
Brett

Re: clip "playing_status" using the bang message in JavaScript

Posted: Sun Jan 16, 2011 12:49 am
by DirectGumby
Hello all,

Here is what I decided to try:

1) Update my genaric "ProertyCallBack" to have one specific type PlayingStatusChange
2) Put a simple post message in the callback to see when it is fired.

Here is what I have:

I recurse through all of my children, when I get to a child I go through all of its properties.
When I setup the property handler I setup one for PlayingStatusChangeCallback.
After that it never gets called again even when I trigger something to play.

// debug output from Max
js: ------:Property: [ 4 ] property playing_status int
js: =Enter=> PlayingStatusChangeCallback
js: =Enter=> PlayingStatusChangeCallback

Trigger play/stop on a clipSlot nothing happens.

Any thoughts on this?

Thanks,
Brett

Re: clip "playing_status" using the bang message in JavaScript

Posted: Sun Jan 23, 2011 9:49 pm
by julienb
I suggest you to check my protodeck's code.
It is a mods of a code initially by Andrew Pask & Darwin Grosse.

If you have questions, bang them :)

Code: Select all

/*
/////////////////////////////////////////////////////////////////////////////

Javascript Live API remote controller and Live set follower

20Objects LLC
20Objects.com
Written by
Andrew Pask			[email protected]
Darwin Grosse		[email protected]


Deeply tweaked for specific protodeck usage
Julien Bayle		[email protected] AKA protofuse

//////////////////////////////////////////////////////////////////////////////
*/

autowatch = 1;
outlets = 3;

const GRID_X_SIZE = 8;
const GRID_Y_SIZE = 6;

var scene = 0;
var num_scenes;
var num_tracks = 15;
var notePitch;

clip_slot_grid = new Array();
liveset_scenes = new Array();
clip_grid = new Array();
playing_clip_grid = new Array();

///////////////   Set up arrays and observe tracks and scenes in the Live set   /////////////////
function set_up()
 {

    scene_observer = new LiveAPI(this.patcher, "live_set");
    if (!scene_observer)
    {
        post("no api object","\n");
    }

    num_scenes = scene_observer.getcount("scenes");
    for (y = 0; y < num_scenes; y++)
    {
        liveset_scenes[y] = new LiveAPI(this.patcher, "live_set scenes " + y);
        if (!liveset_scenes[y])
        {
            post("no api object","\n");
        }
    }
    
    for (x = 0; x < num_tracks; x++)
    {
        clip_grid[x] = new Array();
        clip_slot_grid[x] = new Array();
    }
    
    scanALL();

     outlet(1, 0);     // current initial song is 1
     outlet(2, num_scenes / GRID_Y_SIZE);     // fire the total number of songs
}


function bang()
{
    set_up();
}

////////////////  Create has_clip observers for each clip_slot fro the WHOLE live_set  ////////////////
function scanALL()
 {
    for (x = 0; x < 15; x++)
    {
        for (y = 0; y < num_scenes ; y++)
        {
            if (!clip_slot_grid[x][y])
            // don't need to create them if they already exist
            {
                clip_slot_grid[x][y] = new LiveAPI(this.patcher, device_callback, "live_set", "tracks", x, "clip_slots", y);
                if (!clip_slot_grid[x][y])
                {
                    post("no api object","\n");
                }
                clip_slot_grid[x][y].track = x;
                clip_slot_grid[x][y].slot = y;
                clip_slot_grid[x][y].property = "has_clip";
                
                clip_grid[x][y] = new LiveAPI(this.patcher, device_callback, "live_set", "tracks", x, "clip_slots", y, "clip");
                if (!clip_grid[x][y])
                {
                    post("no api object","\n");
                }
                clip_grid[x][y].track = x;
                clip_grid[x][y].slot = y;
                clip_grid[x][y].property = "playing_status";
                
            }
        }
    }
}


////////////////////////  Forging midi bytes for the current song for protodeck updates  ////////////////////
function output_midi()
 {    
    for (x = 2; x < 15 ; x++)
    {    
        if ( (x==2 || (x>=8 && x<=14)) )
        {
            for (y = scene; y < GRID_Y_SIZE + scene; y++)
            {
                if (clip_slot_grid[x][y].get("has_clip") == 1)
                {
                    if (clip_grid[x][y].get("is_playing") == 1)
                    {
                      outlet(0, x + " " + y + " 32");     // green  for  clip playing
                    }
                    else 
					
					{
					if (clip_grid[x][y].get("is_triggered") == 1)
						{
							outlet(0, x + " " + y + " 48");     // yellow for  clip triggered
						}
						else
						{
						   if (clip_grid[x][y].name == "R")  outlet(0, x + " " + y + " 80");    // purple for clip not playing & containing a rythm
						   else outlet(0, x + " " + y + " 64");    // blue  for  clip not playing
						}
					}
                }
                else
                {
                    outlet(0, x + " " + y + " 1");     // off  for  empty clipslot
                }
            }
        }
    }
}


////////////////////////////  Scrolling the view around  //////////////////////////////
function next()
 {
    if (scene < (num_scenes - GRID_Y_SIZE))
    {
        scene += GRID_Y_SIZE;
        output_midi();
        outlet(1, scene / GRID_Y_SIZE);     // fire out the current song number for LCD
    }
}

function prev()
 {
    if (scene >= GRID_Y_SIZE)
    {
        scene -= GRID_Y_SIZE;
        output_midi();
        outlet(1, scene / GRID_Y_SIZE);     // fire out the current song number for LCD
    }
}


///////////////////  Handle clip,scene firing and transport calls from cellblock  ///////////////
function fire(x, y)
 {
    if (x == "scene")
    {
        liveset_scenes[y + scene].call("fire");

    }
    else
    {
        if (clip_slot_grid[x][y + scene].get("has_clip") == 1)
        {   
            var sum = y + scene ;
            clip_grid[x][y + scene].call("fire");
        }
    }
}


////////////////////  Catch-all callback function  ////////////////////
function device_callback(args)
 {
    switch (args[0])
    {
    case "id":

        //
        break;
        
        ///////////////// Handle empty clip slot   /////////////////        
    case "has_clip":

        var x = this.track ;
        var y = this.slot ;
            if (clip_slot_grid[x][y].get("has_clip") == 0)
            {
                if ( y>= scene && y<scene+GRID_Y_SIZE ) outlet(0, x + " " + y + " 1");
            }
        break;
    
    ///////////////// Handle changes in clip playing status   /////////////////        
    case "playing_status":

        var x = this.track ;
        var y = this.slot ;

        if ( y>= scene && y<scene+GRID_Y_SIZE  && (x==2 || (x>=8 && x<=14)) ) // only fire midi bytes updates for the current observed scene & only for signifiant tracks
            {
                if (clip_slot_grid[x][y].get("has_clip") == 1)
                {
                    if (clip_grid[x][y].get("is_playing") == 1)
                    {
                      outlet(0, x + " " + y + " 32");            // green  for  clip playing
                    }
                    else if (clip_grid[x][y].get("is_triggered") == 1)
                    {
                         outlet(0, x + " " + y + " 48");        // yellow for  clip triggered
                    }
                    else
                    {
                       if (x == 2 && clip_grid[x][y].get("name") == "R")
                       {
                            outlet(0, x + " " + y + " 80");        // purple for clip not playing & containing a rythm  
                       }    
                       else outlet(0, x + " " + y + " 64");        // blue  for  clip not playing
                    }
                }
                else
                {
                   outlet(0, x + " " + y + " 1");                 // off  for  empty clipslot
                }

            }
            
        break;
    }
}

Re: clip "playing_status" using the bang message in JavaScript

Posted: Mon Jan 24, 2011 1:38 am
by Surreal

Code: Select all

if (gWatchClipPlayingStatus) { //to reuse the old one if it exists
    gWatchClipPlayingStatus.goto("live_set tracks " + TRACK_NUMBER + " clip_slots " + SCENE_NUMBER + " clip");
}
else {
    gWatchClipPlayingStatus = new LiveAPI(this.patcher, NAME_OF_LISTENER, "live_set tracks " + TRACK_NUMBER + " clip_slots " + SCENE_NUMBER + " clip");
}
gWatchClipPlayingStatus.mode = 0; // in case the track is moved
gWatchClipPlayingStatus.property = "playing_status";
then, in NAME_OF_LISTENER()

Code: Select all

var clipIsPlaying = gWatchClipPlayingStatus.get("is_playing");
var clipIsRecoding = gWatchClipPlayingStatus.get("is_recording");
this was helpful to me when i started : http://pastie.org/627540

Re: clip "playing_status" using the bang message in JavaScript

Posted: Mon Jan 24, 2011 1:46 am
by Surreal
or you could post code.

Re: clip "playing_status" using the bang message in JavaScript

Posted: Fri Jan 28, 2011 6:14 am
by DirectGumby
Thank you!!!

I'll give it a shot this weekend.

Brett