simulator

This commit is contained in:
Seth Call 2026-02-23 10:43:42 -06:00
parent 23da778f6c
commit 9861d1f908
9 changed files with 415 additions and 23 deletions

View File

@ -30,6 +30,29 @@
var backingTrackPath = "";
var backingTrackLoop = false;
var simulateNoInputs = false;
var captureResolution = 2;
var metronomeCricketTestState = false;
var genericCallbackName = null;
var sessionJoinLeaveCallbackName = null;
var jamBlasterAutoPair = false;
var jamBlasterPortState = {use_static_port: false, static_port: 12000};
var jamBlasterNetworkState = {dhcp: true, addr: "", subnet: "", gateway: "", dns1: "", dns2: ""};
var jamBlasterTrackState = {
has_chat: true,
input1_linemode: false,
input2_linemode: false,
input1_48V: false,
input2_48V: false,
track1: {stereo: false, left: true, right: false, inst: 10},
track2: {stereo: false, left: false, right: true, inst: 10}
};
var jamBlasterPhantomAndLineState = {
input1_linemode: false,
input2_linemode: false,
input1_48V: false,
input2_48V: false
};
var vstScanPaths = {paths: []};
function dbg(msg) {
logger.debug('FakeJamClient: ' + msg);
@ -142,6 +165,25 @@
return {}
}
function FTUEGetCaptureResolution() {
return {
1: "CIF (352X288)",
2: "VGA (640X480)",
3: "4CIF (704X576)",
4: "1/2WHD (640X360)",
5: "WHD (1280X720)",
6: "FHD (1920x1080)"
};
}
function FTUEGetCurrentCaptureResolution() {
return captureResolution;
}
function FTUESetCaptureResolution(resolution) {
captureResolution = resolution;
}
function FTUESetSendFrameRates(fps) {
}
@ -1492,6 +1534,284 @@
function SaveSettings() {
}
function GetFTUE() {
return ftueStatus;
}
function SetFTUE(val) {
ftueStatus = !!val;
return true;
}
function BringVideoWindowToFront() {
}
function ClientJoinedSession(sourceUserId, clientId, sessionId) {
}
function ClientLeftSession(sourceUserId, clientId, sessionId) {
}
function RegisterGenericCallBack(callbackName) {
genericCallbackName = callbackName;
return true;
}
function RegisterSessionJoinLeaveRequestCallBack(callbackName) {
sessionJoinLeaveCallbackName = callbackName;
return true;
}
function SessionPausePlay() {
}
function SessionTrackSeekMs(seekMs) {
}
function SessionJamTrackSeekMs(seekMs) {
}
function SessionShowMetronomeGui() {
}
function ShowSelectBackingTrackDialog(callbackName) {
return true;
}
function openBackingTrackFile(path) {
SessionOpenBackingTrackFile(path, false);
return true;
}
function OpenBackingTracksDirectory() {
return true;
}
function GetJamTrackTimeline() {
return {events: []};
}
function InvalidateJamTrack(fqId) {
return true;
}
function JamTrackLoadJmep(fqId, jmep) {
return true;
}
function StartLiveStreaming(streamName) {
return true;
}
function StopLiveStreaming() {
return true;
}
function TrackSetChatInput(channelId) {
return true;
}
function UpdateSessionInfo(sessionInfo) {
return true;
}
function VSTClearAll() {
return true;
}
function VSTListVsts() {
return getPluginList();
}
function VSTListTrackAssignments() {
return listTrackAssignments();
}
function VSTListSearchPaths() {
return vstScanPaths;
}
function VSTAddSearchPath(typeId, pathToAdd) {
if (!pathToAdd) {
return true;
}
if ($.inArray(pathToAdd, vstScanPaths.paths) < 0) {
vstScanPaths.paths.push(pathToAdd);
}
return true;
}
function VSTRemoveSearchPath(typeId, pathToRemove) {
vstScanPaths.paths = $.grep(vstScanPaths.paths, function (scanPath) {
return scanPath !== pathToRemove;
});
return true;
}
function VSTSetTrackAssignment(vst, trackId) {
return {success: true};
}
function VSTShowHideGui(show, trackId) {
return true;
}
function ShowSelectVSTScanDialog(callbackName) {
if (callbackName) {
setTimeout(function () {
eval(callbackName + "({success:false,vstPath:''})");
}, 0);
}
return true;
}
function VST_ScanForMidiDevices() {
return true;
}
function VST_GetMidiDeviceList() {
return {midiDevices: []};
}
function VST_EnableMidiForTrack(trackId, enableMidi, midiDeviceIndex) {
return true;
}
function setMetronomeCricketTestState(enabled) {
metronomeCricketTestState = !!enabled;
return true;
}
function getMetronomeCricketTestState() {
return metronomeCricketTestState;
}
function setSessionMixerCategoryPlayoutState(isMusic, controlGroups) {
return true;
}
function getOpenVideoSources() {
return [];
}
function openVideo(recordingId) {
return true;
}
function uploadVideo(recordingId, authToken, videoInfoJson, progressCallbackName, doneCallbackName, failCallbackName) {
if (progressCallbackName) {
setTimeout(function () {
eval(progressCallbackName + "(1024,10240)");
}, 50);
}
if (doneCallbackName) {
setTimeout(function () {
eval(doneCallbackName + "('fake-video-id')");
}, 100);
}
return {};
}
function pauseVideoUpload() {
return true;
}
function resumeVideoUpload() {
return true;
}
function cancelVideoUpload() {
return true;
}
function deleteVideo(recordingId) {
return true;
}
function VideoDecision(recordingId, name, keepResult) {
return true;
}
function getLocalClients() {
return [];
}
function getJBAutoPair() {
return jamBlasterAutoPair;
}
function setJBAutoPair(autopair) {
jamBlasterAutoPair = !!autopair;
return true;
}
function getJbPortBindState() {
return $.extend({}, jamBlasterPortState);
}
function setJbPortBindState(state) {
jamBlasterPortState = $.extend({}, jamBlasterPortState, state);
return true;
}
function getJbNetworkState() {
return $.extend({}, jamBlasterNetworkState);
}
function setJbNetworkState(state) {
jamBlasterNetworkState = $.extend({}, jamBlasterNetworkState, state);
return true;
}
function getJbTrackState() {
return $.extend(true, {}, jamBlasterTrackState);
}
function setJbTrackState(audio) {
jamBlasterTrackState = $.extend(true, {}, jamBlasterTrackState, audio);
jamBlasterPhantomAndLineState = $.extend({}, jamBlasterPhantomAndLineState, {
input1_linemode: !!jamBlasterTrackState.input1_linemode,
input2_linemode: !!jamBlasterTrackState.input2_linemode,
input1_48V: !!jamBlasterTrackState.input1_48V,
input2_48V: !!jamBlasterTrackState.input2_48V
});
return true;
}
function get48vAndLineInstState() {
return $.extend({}, jamBlasterPhantomAndLineState);
}
function set48vAndLineInstState(update) {
jamBlasterPhantomAndLineState = $.extend({}, jamBlasterPhantomAndLineState, update);
jamBlasterTrackState = $.extend(true, {}, jamBlasterTrackState, jamBlasterPhantomAndLineState);
return true;
}
function jamBlasterSerialNo() {
return "SIMULATED-JAMBLASTER";
}
function setJBName(name) {
return {success: true};
}
function startPairing(connectUrl) {
return true;
}
function endPairing() {
return true;
}
function rebootJamBlaster() {
return true;
}
function getAllClientsStateMap() {
return {};
}
function GetUseStaticPort() {
return false;
}
@ -1570,10 +1890,13 @@
this.LeaveSessionAndMinimize = LeaveSessionAndMinimize;
this.GetAutoStart = GetAutoStart;
this.SetAutoStart = SetAutoStart;
this.GetFTUE = GetFTUE;
this.SetFTUE = SetFTUE;
this.GetUseStaticPort = GetUseStaticPort;
this.SetUseStaticPort = SetUseStaticPort;
this.GetStaticPort = GetStaticPort;
this.SetStaticPort = SetStaticPort;
this.SaveSettings = SaveSettings;
this.connected = true;
// FTUE (round 3)
@ -1706,6 +2029,8 @@
this.JamTrackGetTrackDetail = JamTrackGetTrackDetail;
this.JamTrackKeysRequest = JamTrackKeysRequest;
this.JamTrackDownload = JamTrackDownload;
this.JamTrackLoadJmep = JamTrackLoadJmep;
this.InvalidateJamTrack = InvalidateJamTrack;
// Scoring Knobs
this.GetScoreWorkTimingInterval = GetScoreWorkTimingInterval;
@ -1716,12 +2041,23 @@
this.SessionCloseBackingTrackFile = SessionCloseBackingTrackFile;
this.SessionOpenBackingTrackFile = SessionOpenBackingTrackFile;
this.SessionSetBackingTrackFileLoop = SessionSetBackingTrackFileLoop;
this.openBackingTrackFile = openBackingTrackFile;
this.OpenBackingTracksDirectory = OpenBackingTracksDirectory;
this.GetJamTrackTimeline = GetJamTrackTimeline;
this.ShowSelectBackingTrackDialog = ShowSelectBackingTrackDialog;
// Metronome:
this.SessionCloseMetronome = SessionCloseMetronome;
this.SessionOpenMetronome = SessionOpenMetronome;
this.SessionSetMetronome = SessionSetMetronome;
this.SessionShowMetronomeGui = SessionShowMetronomeGui;
this.SessionPausePlay = SessionPausePlay;
this.SessionTrackSeekMs = SessionTrackSeekMs;
this.SessionJamTrackSeekMs = SessionJamTrackSeekMs;
this.setMetronomeOpenCallback = setMetronomeOpenCallback;
this.setMetronomeCricketTestState = setMetronomeCricketTestState;
this.getMetronomeCricketTestState = getMetronomeCricketTestState;
this.setSessionMixerCategoryPlayoutState = setSessionMixerCategoryPlayoutState;
this.getMyNetworkState = getMyNetworkState;
this.getPeerState = getPeerState;
@ -1763,6 +2099,9 @@
this.FTUECurrentSelectedVideoDevice = FTUECurrentSelectedVideoDevice;
this.FTUEGetAvailableEncodeVideoResolutions = FTUEGetAvailableEncodeVideoResolutions;
this.FTUEGetVideoCaptureDeviceCapabilities = FTUEGetVideoCaptureDeviceCapabilities;
this.FTUEGetCaptureResolution = FTUEGetCaptureResolution;
this.FTUEGetCurrentCaptureResolution = FTUEGetCurrentCaptureResolution;
this.FTUESetCaptureResolution = FTUESetCaptureResolution;
this.FTUEGetSendFrameRates = FTUEGetSendFrameRates;
this.FTUESetSendFrameRates = FTUESetSendFrameRates;
this.GetCurrentVideoResolution = GetCurrentVideoResolution;
@ -1792,23 +2131,70 @@
// Broadcasting
this.SessionLiveBroadcastStart = SessionLiveBroadcastStart;
this.SessionLiveBroadcastStop = SessionLiveBroadcastStop;
this.StartLiveStreaming = StartLiveStreaming;
this.StopLiveStreaming = StopLiveStreaming;
this.BringVideoWindowToFront = BringVideoWindowToFront;
this.SessionSetConnectionStatusRefreshRate = SessionSetConnectionStatusRefreshRate;
this.ClientJoinedSession = ClientJoinedSession;
this.ClientLeftSession = ClientLeftSession;
this.UpdateSessionInfo = UpdateSessionInfo;
// fake calls; not a part of the actual jam client
this.RegisterP2PMessageCallbacks = RegisterP2PMessageCallbacks;
this.SetFakeRecordingImpl = SetFakeRecordingImpl;
this.RegisterGenericCallBack = RegisterGenericCallBack;
this.RegisterSessionJoinLeaveRequestCallBack = RegisterSessionJoinLeaveRequestCallBack;
// network test
this.TestNetworkPktBwRate = TestNetworkPktBwRate;
this.StopNetworkTest = StopNetworkTest;
this.NetworkTestResult = NetworkTestResult;
this.log = log;
this.getOperatingMode = getOperatingMode;
this.TrackSetChatInput = TrackSetChatInput;
this.VSTLoad = VSTLoad;
this.VSTScan = VSTScan;
this.VSTClearAll = VSTClearAll;
this.VSTListVsts = VSTListVsts;
this.VSTListTrackAssignments = VSTListTrackAssignments;
this.VSTListSearchPaths = VSTListSearchPaths;
this.VSTAddSearchPath = VSTAddSearchPath;
this.VSTRemoveSearchPath = VSTRemoveSearchPath;
this.VSTSetTrackAssignment = VSTSetTrackAssignment;
this.VSTShowHideGui = VSTShowHideGui;
this.ShowSelectVSTScanDialog = ShowSelectVSTScanDialog;
this.VST_ScanForMidiDevices = VST_ScanForMidiDevices;
this.VST_GetMidiDeviceList = VST_GetMidiDeviceList;
this.VST_EnableMidiForTrack = VST_EnableMidiForTrack;
this.hasVstHost = hasVstHost;
this.getPluginList = getPluginList;
this.clearPluginList = clearPluginList;
this.listTrackAssignments = listTrackAssignments;
this.getLocalClients = getLocalClients;
this.getJBAutoPair = getJBAutoPair;
this.setJBAutoPair = setJBAutoPair;
this.getJbPortBindState = getJbPortBindState;
this.setJbPortBindState = setJbPortBindState;
this.getJbNetworkState = getJbNetworkState;
this.setJbNetworkState = setJbNetworkState;
this.getJbTrackState = getJbTrackState;
this.setJbTrackState = setJbTrackState;
this.get48vAndLineInstState = get48vAndLineInstState;
this.set48vAndLineInstState = set48vAndLineInstState;
this.jamBlasterSerialNo = jamBlasterSerialNo;
this.setJBName = setJBName;
this.startPairing = startPairing;
this.endPairing = endPairing;
this.rebootJamBlaster = rebootJamBlaster;
this.getAllClientsStateMap = getAllClientsStateMap;
this.getOpenVideoSources = getOpenVideoSources;
this.openVideo = openVideo;
this.uploadVideo = uploadVideo;
this.pauseVideoUpload = pauseVideoUpload;
this.resumeVideoUpload = resumeVideoUpload;
this.cancelVideoUpload = cancelVideoUpload;
this.deleteVideo = deleteVideo;
this.VideoDecision = VideoDecision;
this.applySubscriptionPolicy = applySubscriptionPolicy;
this.clientID = "devtester";
};

View File

@ -253,7 +253,7 @@ profileUtils = context.JK.ProfileUtils
onboardings = []
if @state.fetchingOnboardings
onboardings.push(`<tr>
onboardings.push(`<tr key="fetching-students">
<td colSpan="6" style={{textAlign:'center'}}>FETCHING STUDENTS</td>
</tr>`)
else if @state.onboardings.length > 0
@ -372,7 +372,7 @@ profileUtils = context.JK.ProfileUtils
</tr>`
onboardings.push(onboarding)
else
onboardings.push(`<tr>
onboardings.push(`<tr key="no-students-assigned">
<td colSpan="6" style={{textAlign:'center'}}>NO STUDENTS ASSIGNED</td>
</tr>`)
@ -425,4 +425,4 @@ profileUtils = context.JK.ProfileUtils
</div>
</div>
</div>`
})
})

View File

@ -88,7 +88,7 @@ SessionStore = @SessionStore
if @state.channel == 'lesson'
chatTabs = `<div className="chat-tabs">
<a data-lesson-id={this.state.lessonSessionId} className="lesson-session-actions-btn"
onClick={this.openMenu.bind(this, {id: this.state.lessonSessionId})}>attach file
onClick={(e) => this.openMenu({id: this.state.lessonSessionId}, e)}>attach file
<div className="details-arrow arrow-down"/>
</a>
</div>`
@ -114,7 +114,7 @@ SessionStore = @SessionStore
if display == 'Unknown'
continue
tabs.push(`<div key={channel} className={classNames(classes)}><a onClick={this.activateChannel.bind(this, channel)}>{display}</a></div>`)
tabs.push(`<div key={channel} className={classNames(classes)}><a onClick={(e) => this.activateChannel(channel, e)}>{display}</a></div>`)
chatTabs = `<div className="chat-tabs">
{tabs}
</div>`
@ -129,7 +129,7 @@ SessionStore = @SessionStore
activeChannel = @state.channel
if activeChannel == 'global'
openBig = `<a className="make-big" href="#" onClick={this.openChatDialog.bind(this)}>Expand</a>`
openBig = `<a className="make-big" href="#" onClick={this.openChatDialog}>Expand</a>`
activeMsgs = @state.msgs[activeChannel] || []
@ -148,13 +148,13 @@ SessionStore = @SessionStore
additional = null
if msg.purpose == 'Notation File'
additional = `<a className="additional" onClick={this.notationClicked.bind(this, msg.music_notation)}>{msg.music_notation.file_name}</a>`
additional = `<a className="additional" onClick={(e) => this.notationClicked(msg.music_notation, e)}>{msg.music_notation.file_name}</a>`
else if msg.purpose == 'Audio File'
additional = `<a className="additional" onClick={this.audioClicked.bind(this, msg.music_notation)}>{msg.music_notation.file_name}</a>`
additional = `<a className="additional" onClick={(e) => this.audioClicked(msg.music_notation, e)}>{msg.music_notation.file_name}</a>`
else if msg.purpose == 'JamKazam Recording'
additional = `<a className="additional" onClick={this.recordingClicked.bind(this, msg.claimed_recording)}>{msg.claimed_recording.name}</a>`
additional = `<a className="additional" onClick={(e) => this.recordingClicked(msg.claimed_recording, e)}>{msg.claimed_recording.name}</a>`
else if msg.purpose == 'Video Uploaded'
additional = `<a className="additional" onClick={this.videoClicked.bind(this, msg.claimed_recording)}>Watch on YouTube</a>`
additional = `<a className="additional" onClick={(e) => this.videoClicked(msg.claimed_recording, e)}>Watch on YouTube</a>`
msgs.push(`<div key={msg.msg_id} className="chat-message">
<span className="chat-message-sender">{sender}</span>{purpose}<time className="chat-message-timestamp timeago">{timeago}</time>
@ -176,7 +176,7 @@ SessionStore = @SessionStore
if this.props.rootClass == 'ChatDialog'
attachFiles = `<a id="attach-files-chat-dialog" data-lesson-id={this.state.lessonSessionId} className="lesson-session-actions-btn"
onClick={this.openMenu.bind(this, {id: this.state.lessonSessionId})}>attach file
onClick={(e) => this.openMenu({id: this.state.lessonSessionId}, e)}>attach file
<div className="details-arrow arrow-down"/>
</a>`

View File

@ -33,7 +33,7 @@ LatencyActions = @LatencyActions
<h3>How This Page Works</h3>
<p>This page will show sessions tailored for you:</p>
<ul>
<li>sessions created by a friend (<a href='#' onClick={this.inviteFriends.bind(this)}>invite others to JamKazam</a>)</li>
<li>sessions created by a friend (<a href='#' onClick={this.inviteFriends}>invite others to JamKazam</a>)</li>
<li>sessions for which you have an invitation</li>
<li>sessions for which you have a RSVP</li>
</ul>
@ -48,7 +48,7 @@ LatencyActions = @LatencyActions
<p>This page will show these scheduled sessions:</p>
<ul>
<li>public jam sessions</li>
<li>sessions created by a friend (<a href='#' onClick={this.inviteFriends.bind(this)}>invite others to JamKazam</a>)</li>
<li>sessions created by a friend (<a href='#' onClick={this.inviteFriends}>invite others to JamKazam</a>)</li>
<li>sessions for which you have an invitation</li>
<li>sessions for which you have a RSVP</li>
</ul>
@ -101,7 +101,7 @@ LatencyActions = @LatencyActions
<div className="refresh-btn">
<a href="/client#/findSession" style={{textDecoration:'none'}} disabled={this.state.searching}
className={refreshButtonClasses} onClick={this.refresh.bind(this)}>REFRESH<span className="extra"></span></a>
className={refreshButtonClasses} onClick={this.refresh}>REFRESH<span className="extra"></span></a>
</div>
<div className="search-box">
<input className="session-keyword-srch" type="text" name="search"

View File

@ -57,7 +57,7 @@ LessonTimerActions = context.LessonTimerActions
componentDidMount: () ->
@root = $(@getDOMNode())
componentWillUpdate: (nextProps, nextState) ->
UNSAFE_componentWillUpdate: (nextProps, nextState) ->
# associate time info from LessonTimerStore with our lesson info
if nextState.lessonTimes? && nextState.lesson_sessions?.entries?
for lesson in nextState.lesson_sessions.entries
@ -633,4 +633,4 @@ LessonTimerActions = context.LessonTimerActions
'teacher'
else
'student'
})
})

View File

@ -14,8 +14,8 @@ RecordingActions = @RecordingActions
this.props.app.layout.showDialog('chat-dialog', {d1: 'session_' + this.props.sessionId})
render: () ->
`<a className="session-record button-grey left" onClick={this.openChat.bind(this)}>
`<a className="session-record button-grey left" onClick={this.openChat}>
<img src="/assets/content/icon_open_folder.png" align="texttop" height="14" width="14"/>
FILES
</a>`
})
})

View File

@ -43,10 +43,10 @@ BackendToFrontendFPS = {
if videoEnabled
currentDevice = context.jamClient.FTUECurrentSelectedVideoDevice()
deviceNames = context.jamClient.FTUEGetVideoCaptureDeviceNames()
deviceNames = if context.jamClient.FTUEGetVideoCaptureDeviceNames? then context.jamClient.FTUEGetVideoCaptureDeviceNames() else {}
#deviceCaps = context.jamClient.FTUEGetVideoCaptureDeviceCapabilities()
captureResolutions = context.jamClient.FTUEGetCaptureResolution()
currentCaptureResolution = context.jamClient.FTUEGetCurrentCaptureResolution()
captureResolutions = if context.jamClient.FTUEGetCaptureResolution? then context.jamClient.FTUEGetCaptureResolution() else {}
currentCaptureResolution = if context.jamClient.FTUEGetCurrentCaptureResolution? then context.jamClient.FTUEGetCurrentCaptureResolution() else null
logger.debug("captureResolutions, currentCaptureResolution", captureResolutions, currentCaptureResolution)
else
@ -128,6 +128,8 @@ BackendToFrontendFPS = {
onSetCaptureResolution: (resolution) ->
@logger.debug("set capture resolution: #{resolution}")
return unless context.jamClient.FTUESetCaptureResolution?
context.jamClient.FTUESetCaptureResolution(resolution)
@state.currentCaptureResolution = resolution
this.trigger(@state)

View File

@ -253,7 +253,10 @@ context.JK.WebcamViewer = class WebcamViewer
selectControl.append option
# load current settings from backend
currentResolution = @client.FTUEGetCaptureResolution()
currentResolution = if @client.FTUEGetCurrentCaptureResolution? then @client.FTUEGetCurrentCaptureResolution() else @client.FTUEGetCaptureResolution()
if typeof(currentResolution) == 'object' && currentResolution?
keys = Object.keys(currentResolution)
currentResolution = if keys.length > 0 then keys[0] else null
selected = currentResolution + '|' + currentFrameRate

View File

@ -8,5 +8,6 @@ if [ ! -z "$1" ]; then
REAL_IP="$1"
fi
NO_WEBSOCKET_GATEWAY=1 bundle exec rails s -b $REAL_IP
#NO_WEBSOCKET_GATEWAY=1 bundle exec rails s -b $REAL_IP
NO_WEBSOCKET_GATEWAY=1 bundle exec rails s -b 0.0.0.0