How to horizontaly scroll through the last positions of your cursor

Hi,

Is it possible to scroll through the last positions of your cursor ?

Kinda like the “edit history” window that allows you to go back in time regarding your actions , I would like to go back in time regarding the positions of my cursor. Is it possible ?

I work with a very wide template and I sometimes get lost in my .cpr so that would allow me to quickly go back where I was horizontally-wise.

(I am aware you can locate the positions of markers)

Thanks a lot !

Hi,

I’m sorry, this feature is not available.

You can add the optional tag feature-request to your post.

Where to exactly? What is the rule to follow? Is it for example the last positions of cursor that you hit “Play” (Or “Stop”)? Is it wherever you clicked?

I like the idea!

Using Midi Remote we can come up with something to do this, Martin. Here’s a snippet which monitors cursor positions, when not in play mode obviously, and sniffing the end of rewind/forward actions. What’s missing from this snippet is the handling of nudges, but it can be done. I’'ve setup 2 buttons for previous/next history cursor position, and limited the history size to 10 entries. Did some tests, it’s working almost OK. But I do see issues :slight_smile:

var midiremote_api=require('midiremote_api_v1')
var deviceDriver = midiremote_api.makeDeviceDriver('Test', 'Cursor History', 'Test')

var midiInput = deviceDriver.mPorts.makeMidiInput()
var midiOutput = deviceDriver.mPorts.makeMidiOutput()

deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
    .expectInputNameEquals('loopMIDI Port 1')
    .expectOutputNameContains('loopMIDI Port 2')
    
var surface=deviceDriver.mSurface

var dummyPlayControl=surface.makeButton(0,0,0,0)
var dummyRewindControl=surface.makeButton(0,0,0,0)
var dummyForwardControl=surface.makeButton(0,0,0,0)
var dummyStopControl=surface.makeButton(0,0,0,0)

var buttonHistoryCursorPrevious=surface.makeButton(0,0,1,1)
buttonHistoryCursorPrevious.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .bindToControlChange(0,24)

var buttonHistoryCursorNext=surface.makeButton(1,0,1,1)
buttonHistoryCursorNext.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .bindToControlChange(0,25)
    


var page=deviceDriver.mMapping.makePage("page")

var maxHistoryCursorSize=10
var delimiter="//"
var delimiterLength=delimiter.length
var sniffForward=true 
var sniffRewind=true 

var dummyHistoryCursorPrevious=page.mCustom.makeHostValueVariable("dummyHistoryCursorPrevious")
page.makeValueBinding(buttonHistoryCursorPrevious.mSurfaceValue,dummyHistoryCursorPrevious).mOnValueChange=function(activeDevice,activeMapping,value){

    if(value==1){

        restoreCursor(activeDevice,activeMapping,-1)

    }
    

}

var dummyHistoryCursorNext=page.mCustom.makeHostValueVariable("dummyHistoryCursorNext")
page.makeValueBinding(buttonHistoryCursorNext.mSurfaceValue,dummyHistoryCursorNext).mOnValueChange=function(activeDevice,activeMapping,value){
    
    if(value==1){

        restoreCursor(activeDevice,activeMapping,1)

    }
    
}


page.makeValueBinding(dummyStopControl.mSurfaceValue,page.mHostAccess.mTransport.mValue.mStop).mOnValueChange=function(activeDevice,activeMapping,stop){

    console.log("stop="+stop)
    activeDevice.setState("stop",""+stop)
    

}

page.makeValueBinding(dummyPlayControl.mSurfaceValue,page.mHostAccess.mTransport.mValue.mStart).mOnValueChange=function(activeDevice,activeMapping,play){

    console.log("play="+play)
    activeDevice.setState("play",""+play)

}

page.makeValueBinding(dummyRewindControl.mSurfaceValue,page.mHostAccess.mTransport.mValue.mRewind).mOnValueChange=function(activeDevice,activeMapping,rewind){

    
    console.log("rewind="+rewind)
    activeDevice.setState("rewind",""+rewind)

    if(rewind==0 && sniffRewind){

        setHistoryCursor(activeDevice,activeDevice.getState("temporaryCursor"))

    }
    
}

page.makeValueBinding(dummyForwardControl.mSurfaceValue,page.mHostAccess.mTransport.mValue.mForward).mOnValueChange=function(activeDevice,activeMapping,forward){

    console.log("forward="+forward)
    activeDevice.setState("forward",""+forward)
    if(forward==0 && sniffForward){

        setHistoryCursor(activeDevice,activeDevice.getState("temporaryCursor"))

    }

}



page.mHostAccess.mTransport.mTimeDisplay.mPrimary.mTransportLocator.mOnChange=function(activeDevice,activeMapping,arg1,arg2){
    
    if(activeDevice.getState("restoringCursor")=="1"){

        activeDevice.setState("restoringCursor","0")
        return 

    }

    var cursorPosition=arg1 
    
    if((activeDevice.getState("rewind")=="1" && sniffRewind) || (activeDevice.getState("forward")=="1" && sniffForward)){

        activeDevice.setState("temporaryCursor",cursorPosition)

    } else if(activeDevice.getState("play")=="0" && activeDevice.getState("rewind")=="0" && activeDevice.getState("forward")=="0"){
        
        setHistoryCursor(activeDevice,cursorPosition)
    
    }

}

function setHistoryCursor(activeDevice,cursorPosition){
    if(cursorPosition=="" || cursorPosition==undefined){
        return 
    }
    console.log("setting cursor to "+cursorPosition)
    var historyCursorSizeStr=activeDevice.getState("historyCursorSize")
    var historyCursors=activeDevice.getState("historyCursors")
    var historyCursorSize=historyCursorSizeStr=="" ? 0 : parseInt(historyCursorSizeStr)
    
    historyCursorSize++
    
    if(historyCursorSize<maxHistoryCursorSize){
    
        activeDevice.setState("historyCursorSize",""+historyCursorSize)
    
    } else {

            historyCursorSize=maxHistoryCursorSize
            historyCursors=historyCursors.substring(historyCursors.indexOf(delimiter)+delimiterLength)

    }
    
    historyCursors=historyCursors+cursorPosition+delimiter
    
    activeDevice.setState("historyCursors",historyCursors)

    activeDevice.setState("historyCursorIndex",(historyCursorSize-1).toString())
    
    console.log("historyCursors="+historyCursors)

}

function restoreCursor(activeDevice,activeMapping,step){

    var historyCursorSizeStr=activeDevice.getState("historyCursorSize")
    var historyCursorSize=historyCursorSizeStr=="" ? 0 : parseInt(historyCursorSizeStr)

    if(historyCursorSize==0){

        return 
    }

    var historyCursorIndexStr=activeDevice.getState("historyCursorIndex")

    var historyCursorIndex=historyCursorIndexStr=="" ? 0 : parseInt(historyCursorIndexStr)

    historyCursorIndex+=step 

    if(historyCursorIndex<0){

        historyCursorIndex=0

    } else if (historyCursorIndex>historyCursorSize-1){

        historyCursorIndex=historyCursorSize-1

    }

    var historyCursors=activeDevice.getState("historyCursors")
    var arrHistoryCursors=historyCursors.substring(0,historyCursors.length-delimiterLength).split(delimiter)
    var fromHistoryCursor=arrHistoryCursors[historyCursorIndex]

    activeDevice.setState("restoringCursor","1")
    activeDevice.setState("historyCursorIndex",""+historyCursorIndex)

    page.mHostAccess.mTransport.mTimeDisplay.mPrimary.mTransportLocator.setTime(activeMapping,fromHistoryCursor)    

}

deviceDriver.mOnActivate=function(activeDevice){
 
    console.log("activating")
    activeDevice.setState("play","0")
    activeDevice.setState("rewind","0")
    activeDevice.setState("forward","0")

}
1 Like

yeah for instance ! :slight_smile:

For three month now I compose all my pieces in the same cpr. This is why my .cpr gets pretty wide !

Is there a reason you don’t use markers? Seems like it would be the perfect solution for navigating a large project.

I do use markers a lot and I often ended up doing that for that purpose.

However personally I find it not always super efficient for instance you cannot look for a specific marker by typing its name, just like you can search for a track with the “find track” fonction.
(I hate looking for things :stuck_out_tongue_closed_eyes:)