Compare commits

...

279 Commits

Author SHA1 Message Date
Seth Call 5a68b57a76 track utm_id 2026-02-04 21:53:36 -06:00
Seth Call 577bece75e Add threads to sources 2026-02-04 19:53:53 -06:00
Seth Call 3ee8577153 Fix Event 2026-01-28 20:03:52 -06:00
Seth Call 8aa5ba743e add array support for facebook ad source 2026-01-24 00:01:40 -06:00
Seth Call 3a4b900ebd Support more utm tracking 2026-01-23 23:31:34 -06:00
Seth Call bfbd266466 build this 2026-01-22 22:36:58 -06:00
Seth Call b6fc597f8b fix reporting 2026-01-22 22:18:11 -06:00
Seth Call 9761d8f44d removing rails loger junk 2026-01-19 13:23:33 -06:00
Seth Call 85d2b3fd53 Store / read UTM 2026-01-17 20:57:36 -06:00
Seth Call 0113408780 Add meta tracking to jam-ui 2026-01-16 07:56:26 -06:00
Seth Call a283c39a58 more logging for cAPI event 2026-01-15 08:01:59 -06:00
Seth Call f3d8c4763b Add beter logging 2026-01-15 07:52:05 -06:00
Seth Call e92e54fcd3 Missed some recurly/plan code for yearly 2026-01-14 22:12:58 -06:00
Seth Call 0fd37809c8 add all this stuff in 2026-01-14 21:04:58 -06:00
Nuwan caf3e2b2d5 Update "Zoom weekly office hours" link in Welcome to JamKazam email 2025-09-03 13:58:44 +05:30
Seth Call 6d2211cbb4 VRFS-5627 - VUs get busted when hovering over remote participants who change tracks/leave/change track settings 2025-08-03 11:51:12 -05:00
Seth Call f755e2b0a0 VRFS-5653 - fix Music/Chat slider 2025-08-02 11:04:46 -05:00
Seth Call 80010723ca Force build 2025-07-26 08:34:09 -05:00
Nuwan ef2497d0a4 remove audio delay from recording interface
remove audioDelay input and related code. also removed
the volume control which was on the same interface
2025-07-17 17:15:33 +05:30
Nuwan e6aad11685 remove unused video formats in recording window
remove .mkv, .ts, .flv, and .m3u8 options from the
video format list box, leaving only .mp4 and .mov options
2025-07-03 20:26:46 +05:30
Nuwan Chaturanga db2010e893 Merged in 5628-vu-meter_frequency (pull request #62)
Implement VU meter frequency preference

* Merged promised_based_api_interation into 5628-vu-meter_frequency

* Merge branch '5628-vu-meter_frequency' of bitbucket.org:jamkazam/jam-cloud into 5628-vu-meter_frequency

* force push

* wip

* wip VU meter update pref rendering

* fix for vu meter update

this fixes the previously broken vu meter update based on the user
selected update rate preference.

* Merge branch '5628-vu-meter_frequency' of bitbucket.org:jamkazam/jam-cloud into 5628-vu-meter_frequency


Approved-by: Seth Call
2025-06-20 10:48:47 +00:00
Seth Call 14dbef2be1 Force a build 2025-06-16 11:48:51 -05:00
Seth Call 915fa31f09 Indicate this comes from the 'modern' client 2025-06-15 14:23:50 -05:00
Seth Call c874158bd7 Fix diagnostic for GEAR_SELECTION 2025-06-15 14:22:30 -05:00
Nuwan 369dd10a02 Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2025-06-15 04:02:58 +05:30
Nuwan 41fb6e7a2a force push 2025-06-15 04:02:17 +05:30
Seth Call 6e478d3411 Deactivate web/video setting for now 2025-06-15 04:02:17 +05:30
Nuwan 5ff7b049ce remove noisy log entry 2025-06-15 03:39:08 +05:30
Nuwan 82bc1c408b Implement VU meter frequency preference
render VU meter updates as per the user preference
2025-06-15 01:19:17 +05:30
Seth Call e82fea8d3d Deactivate web/video setting for now 2025-06-13 07:28:29 -05:00
Seth Call 324d34ff61 Recording seems to be working well enough atm. With new clients only 2025-06-08 22:24:37 -05:00
Seth Call e83805bd4a pause 2025-06-08 14:34:23 -05:00
Seth Call 02666d1680 Working on so far. at coffee shop pause 2025-06-08 14:34:10 -05:00
Seth Call d573904d05 pause before change to js 2025-06-07 12:15:08 -05:00
Seth Call cb24078c19 Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2025-05-28 16:38:53 -05:00
Seth Call 4931908344 Update recording feature to show recording in progresso for late joiners. also update start recording button 2025-05-28 16:38:41 -05:00
Nuwan Chaturanga 2983b801f6 Merged in 5538-modal_dialog_to_remind_gear_setup (pull request #60)
5538 modal dialog to remind gear setup

* Setup Gear prompt

Display each time user runs app if Setup Gear step in PLG funnel not yet
completed


Approved-by: Seth Call
2025-05-23 13:01:45 +00:00
Nuwan 194c6156e0 chage references of beta.jamkazam to www.jamkazam 2025-05-21 12:17:06 +05:30
Nuwan 8ae89c1cbb debug custom URL handling in app 2025-04-30 17:40:21 +05:30
Nuwan a17c29216c 5551 2025-04-28 23:35:41 +05:30
Nuwan f88def1790 fixes related to recording state 2025-04-23 11:43:29 +05:30
Nuwan f666578872 add debug log to check recording video state 2025-04-21 15:19:57 +05:30
Nuwan 911a37bec5 fixing state issues of front end recording 2025-04-18 18:15:30 +05:30
Nuwan fdb392f723 wip 2025-04-17 00:35:54 +05:30
Nuwan ce5bb82fb5 wip 2025-04-16 23:47:24 +05:30
Nuwan 0f074b1e37 wip 2025-04-16 23:32:06 +05:30
Nuwan bbf4688830 wip 2025-04-16 23:25:49 +05:30
Nuwan e1b565847c wip 2025-04-16 19:31:34 +05:30
Nuwan c28508bcf7 recording state fix wip 2025-04-10 00:35:26 +05:30
Nuwan fd64e946bf FrontStopRecording api added 2025-04-04 04:46:21 +05:30
Nuwan 844633397f fixes for session recording with other participants 2025-04-04 03:19:00 +05:30
Nuwan ab34c37d80 changes to allow joining a seesion without stopping an onging recording 2025-04-02 18:50:37 +05:30
Nuwan 5d9a75deb3 wip chages in session recording 2025-03-31 13:22:57 +05:30
Nuwan c277fdce94 wip 2025-03-27 18:53:45 +05:30
Nuwan 76aefd6227 wip on leaving a session while recording 2025-03-17 15:51:59 +05:30
Nuwan eb9ad97ada validate custom URLs before processing 2025-02-08 18:34:53 +05:30
Nuwan c82a01361f customUrl validation 2025-02-06 22:11:01 +05:30
Nuwan e2828b0387 notify other participants on session leave
on leaving the session directly delete the participant record and
notify other clients ref: VRFS-5529
2025-02-05 01:04:11 +05:30
Nuwan 254ad61168 recording dialog update
add Audio Files options to select file storage options
add help help bubbles to audio files, audio delay and voice chat
2025-02-04 17:33:41 +05:30
Nuwan 532f29f3db changes to customUrl handling in client 2025-01-30 13:28:15 +05:30
Nuwan 9abaa539db fixes to app loading by custom URLs 2025-01-29 09:50:50 +05:30
Nuwan 0ed89f4e38 customUrl handling fixes 2025-01-28 17:18:58 +05:30
Nuwan 867b159c63 Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2025-01-18 15:27:28 +05:30
Nuwan ccf3b3b5e7 force user to go to new jamtracks page (beta) once user clicks the JamTracks tile in client home page 2025-01-18 15:26:36 +05:30
Seth Call 767e1c7c83 Just how to test the start command 2024-12-14 14:32:12 -06:00
Seth Call fa068ad8be force build 2024-12-01 21:39:53 -06:00
Nuwan 1c47c70d35 custom url debug 2024-11-30 11:12:45 +05:30
Nuwan 80f0fa8bd9 add debug entries to check custom url 2024-11-23 20:00:26 +05:30
Nuwan ea3cecbfcf debug customUrl 2024-11-23 10:23:40 +05:30
Nuwan 9f59074b0e custom URL handling on onLoggedIn 2024-11-23 06:29:28 +05:30
Nuwan ba6c3c56dc joinSession custom URL: change parameter name 2024-11-22 22:59:07 +05:30
Nuwan e262c601b7 custom URL related adjestments 2024-11-17 00:10:20 +05:30
Nuwan f41c64acc8 comment duplicate code 2024-11-16 08:51:29 +05:30
Nuwan 8194e4c636 join session using custom url scheme 2024-11-15 22:18:58 +05:30
Nuwan 8dc3a56870 tweeks to session create from custom URL scheme 2024-11-15 18:06:41 +05:30
Nuwan 0bd3f9463d fixes for creating sessions by custom URL 2024-10-28 09:08:22 +05:30
Nuwan fd8f31e7d4 custom URL schema handling 2024-10-25 17:08:28 +05:30
Nuwan a5fce73848 wip - custom url handling 2024-10-25 08:29:13 +05:30
Nuwan 2b929c0d1e add debug log entries to identify possible errors when creating a session using custom URL 2024-10-23 23:54:13 +05:30
Nuwan 489f3a685d add debug log entries to identify possible errors when creating a session using custom URL 2024-10-23 23:42:48 +05:30
Nuwan cef7f1efbe custom URL schema for create a session
handles URL loaded as a custom URL format (jamkazam://)
which is meant to create a new session with the provided
parameters
2024-10-23 11:33:57 +05:30
Nuwan de115773ec add more logging to debug create session from custom URL 2024-10-18 08:34:35 +05:30
Nuwan 7f693b7e54 bug fixing in custom url app launching 2024-10-17 14:31:49 +05:30
Nuwan 12feacc908 add logging for debugging 2024-10-17 13:49:22 +05:30
Nuwan a718037dd3 customUrl handle - launch jk session screen when is invoked using custom URL 2024-10-17 00:12:22 +05:30
Nuwan c9528feabf assign session if as newSessionId to identify when the session is created 2024-10-16 13:52:56 +05:30
Nuwan 505d7c0496 invoking the client to create a session using custom URL 2024-10-16 12:49:56 +05:30
Nuwan 15583ce99d onLogginIn api handle for custom url wip 2024-10-16 12:49:56 +05:30
Nuwan 1280a3ca86 wip custom url handling 2024-10-16 12:49:56 +05:30
Seth Call 243a081aa9 Make the previously-slow query target feed query configurable. Default to on 2024-10-14 11:19:19 -05:00
Nuwan f71c0913b7 Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2024-10-11 22:05:14 +05:30
Seth Call 1ae5437618 Fix recurly bug where updated 2x from a RJS token 'ruins' the account until the user re-deploys 2024-10-11 22:00:38 +05:30
Nuwan fb80a3a2c5 join session by custom url schema 2024-10-11 22:00:10 +05:30
Nuwan c9a3f7d1da Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2024-10-11 08:54:15 +05:30
Nuwan 98273bae0d handle session invocation by custom URL schema 2024-10-11 08:50:10 +05:30
Seth Call a3e0666202 Fix recurly bug where updated 2x from a RJS token 'ruins' the account until the user re-deploys 2024-10-05 15:55:37 -05:00
Nuwan 317c0384e1 add await on SetScoreWorkTimingInterval 2024-09-26 08:29:49 +05:30
Nuwan 2546d3f550 change order of LaunchBroadcastSettings enum item in asyncJamClient 2024-09-25 22:22:23 +05:30
Nuwan 57e669cd22 session setting fix musician access drop down always disabled 2024-09-21 11:00:28 +05:30
Seth Call 1e50060087 Backport JAM_REASON_PRESENT into user model, to co-exist happily with develop servers 2024-09-17 22:27:27 -05:00
Nuwan 08fe7808a0 remove video gear link from account home page 2024-09-13 08:18:55 +05:30
Nuwan 7ea8a1e8fa Session broadcast button
add broadcast button which send a message to the client
2024-08-21 22:41:23 +05:30
Seth Call 279ba30506 Force build 2024-08-12 12:50:48 -05:00
Nuwan 2a64bbbfe8 fix js reference (this) error in waitForSessionPageEnterDone function 2024-04-11 17:03:28 +05:30
Nuwan 7617e4a4dd use jquery $.deferred in waitForSessionPageEnterDone
change the ES6 promise way of handling this method.
actually some of the code in this file expects $.deferred object
to be presented.
2024-04-11 14:54:48 +05:30
Nuwan 8bb0fa2809 fix not able to delete band 2024-03-09 16:34:21 +05:30
Nuwan 7c2ffe01ef fix band section listing musicians 2024-03-03 17:32:59 +05:30
Nuwan bcd819dfc3 fix recording window glitches
use RecordingStore instead of AppStore to track audioFormat changes.
this prevents session related state being altered unexpectedly.
2023-11-17 16:00:03 +05:30
Nuwan 8d4ed14fd6 sync recording audio format change with back end audio recording menu 2023-11-15 18:46:51 +05:30
Nuwan 03bb4190f1 sync audio recording format
on session startup fetch the audio format selected in the back end
and assign it in the front end audio recording window.
2023-11-14 17:37:19 +05:30
Nuwan 4a30d29c4b fix recording stop
this fix addresses the issue when stopping a recording in a subsequent
attemp to record
2023-10-17 18:09:12 +05:30
Nuwan b185a60656 change enum order of asyncJamClient 2023-10-12 23:08:19 +05:30
Nuwan 2b1309a3b0 change recording allowed video formats 2023-10-04 02:01:01 +05:30
Nuwan c116559d18 clean up comment 2023-10-04 01:17:09 +05:30
Nuwan 0617b1ba8d change in audio formats list for recording 2023-10-04 01:13:45 +05:30
Nuwan 001f59ba30 new session recording feature
for video recordings check if OBS has been installed on the
user's computer.
2023-10-03 19:17:26 +05:30
Nuwan 25586e06fc changes to allowed audio formats in new recording window 2023-10-03 01:16:09 +05:30
Nuwan 5618b08e79 call on start recording the new StartMediaRecording API 2023-09-30 10:07:08 +05:30
Nuwan e9ff7c5faa add IsOBSAvailable api in to asyncJamClient 2023-09-30 00:18:27 +05:30
Nuwan 6acf990b20 add StartMediaRecording api in to asyncJamClient 2023-09-30 00:08:09 +05:30
Nuwan da762dcd2c Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2023-09-29 23:47:16 +05:30
Nuwan e1ff954709 guard session recording 2023-09-29 23:46:42 +05:30
Nuwan c9d7a560d0 debug jamtrack volume 2023-09-29 23:46:42 +05:30
Nuwan 8ef9530129 guard session recording 2023-09-22 16:18:02 +05:30
Nuwan 40282a82f3 debug jamtrack volume 2023-09-21 17:16:08 +05:30
Nuwan 4a2046aae6 handle new recording window events 2023-09-21 10:45:53 +05:30
Nuwan ad9f5dcef3 wip on new session recording window 2023-09-19 13:13:44 +05:30
Nuwan 2dceeb86c3 wip new recording window 2023-09-19 13:13:44 +05:30
Nuwan 5727780259 merge into promised_based_api_interation 2023-09-19 13:12:34 +05:30
Nuwan 2093c6da9e wip new recording window 2023-09-19 13:11:55 +05:30
Nuwan 2adf75eb7e wip new recording 2023-09-19 13:11:55 +05:30
Nuwan a01a10afab WIP recording settings form 2023-09-19 13:11:55 +05:30
Nuwan 3eac4cc4b1 WIP in new session recording window. UI is almost done. need to add functinality 2023-09-19 13:11:55 +05:30
Nuwan 25d651f450 add more volume data to SessionSetTrackVolumeData
id, _id and groupID added to the third parameter of this API call
2023-09-19 11:56:39 +05:30
Nuwan f835894620 add more context details to SessionSetTrackVolumeData
add  mediaType, isJamTrack, and isMetronome to trackVolumeObject parameter
of SessionSetTrackVolumeData api
2023-09-13 18:29:35 +05:30
Nuwan bf1291abf4 removing unused bits 2023-09-07 20:03:34 +05:30
Nuwan 55d3202c11 Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2023-09-05 19:22:16 +05:30
Nuwan 61b58eddd1 prevent showing alert on audio instrument select
fix this bug due to previous introduction of alert which pops up
if midi instrument is selected without selecting midi interface and
vst plugin. The alert only applicable to the midi interface.
2023-09-05 19:19:16 +05:30
Seth Call fc9d69f5f9 Update to pass product from client back to ArtifactUpdate 2023-09-02 15:23:22 -05:00
Seth Call 21733110f4 skip all client updatse 2023-09-02 14:53:19 -05:00
Seth Call f9c3c33d6b Beta download page 2023-09-01 16:33:09 -05:00
Nuwan ccee1c6805 cleanup debug entries 2023-09-01 16:54:01 +05:30
Nuwan f92ae4dd8d debugging 2023-09-01 15:57:35 +05:30
Nuwan 9e2adc9ce0 fix artifact version upgrade 2023-09-01 13:51:16 +05:30
Nuwan c8be3b847f debug JamServer 2023-09-01 13:33:09 +05:30
Nuwan 6d2ef50a8d debug version upgrade 2023-09-01 10:20:46 +05:30
Nuwan 63ebf8259c changes related to client upgrade fixes 2023-09-01 00:45:44 +05:30
Nuwan ea5e32e14b fix recording window handling on conneted clients to the session 2023-08-31 22:22:30 +05:30
Nuwan 7936d8ac59 debug 2023-08-31 09:47:46 +05:30
Nuwan fff48bf399 client update debug logs 2023-08-31 09:36:25 +05:30
Nuwan d0966fe67a debug backing track on peer 2023-08-28 18:14:45 +05:30
Nuwan 4f1fd4880e fix inconsistency of volume gauge
this fixes the unpredictable behavior of volume level when changing the
volume gauge leveler.
2023-08-22 23:09:44 +05:30
Nuwan e3cb68dda8 Show instructions in midi track configuration popup 2023-08-21 16:45:12 +05:30
Nuwan d8d04dd33f Allow multiple recordings within session
change in recording flow. Now after stopping the recording we no longer ask
user to save or discard the recording, instead the app saves the recording to user's
computer and opens the file explorer to that folder.
therefore following scenario is no longer valid; hence skipping it.
2023-08-19 11:03:29 +05:30
Nuwan 701620089a async/await fix 2023-08-11 03:24:11 +05:30
Nuwan 126e08a90d fix for version upgrade alert 2023-08-05 18:07:27 +05:30
Nuwan 48b2316728 debug version upgrade 2023-08-05 17:19:11 +05:30
Nuwan 03e12da98a audio MIDI config alert
show an alert when midi interface or midi plugin is not selected
2023-08-05 00:39:24 +05:30
Nuwan c7822a14d0 more cleaning console logs 2023-08-02 09:15:09 +05:30
Nuwan 758e688db1 remove debug entries and cleanup 2023-08-02 08:57:59 +05:30
Nuwan 5e7d512a5e fix for midi instrument selection 2023-08-02 08:32:11 +05:30
Nuwan 6d4b775321 debugging 2023-07-28 15:52:36 +05:30
Nuwan 2f866e92a7 debugging 2023-07-28 15:19:59 +05:30
Nuwan fd929ab0dc remove debug lines 2023-07-28 12:29:59 +05:30
Nuwan 4fbe7fb8a3 debug websocket gateway handle login 2023-07-28 07:59:03 +05:30
Nuwan 7390355b3c provide detailed os name in jamserver to be consumed by websocket gateway router 2023-07-28 07:53:51 +05:30
Nuwan 9329e5d235 debug logs 2023-07-22 09:50:15 +05:30
Nuwan 5ca37d63c1 debug versioncheck api 2023-07-22 04:32:55 +05:30
Nuwan 20331c6d60 fix for version upgrade 2023-07-22 03:59:49 +05:30
Nuwan 60009208c0 fix for audio input port assignment
this fix addresses the invalid input port assignment issue
due to asynchronous nature of asyncjamClient method calls
2023-07-21 18:32:40 +05:30
Nuwan 81b3fecfd4 fix for client version upgrade 2023-07-20 04:11:44 +05:30
Nuwan e03389909e fix showing error alert on audio resync 2023-07-20 03:31:37 +05:30
Nuwan 483eb20c88 ArtifactsUpdate MacOSX-M 2023-07-12 10:39:57 +05:30
Nuwan e764047935 change in userAgent check to determine client type 2023-07-11 22:30:48 +05:30
Nuwan 287fad8443 Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2023-07-07 18:54:10 +05:30
Nuwan eba15f255e remove alert on session recording stop 2023-07-07 18:53:19 +05:30
Nuwan 42ee0bcf26 WIP fixing midi configuration 2023-07-07 18:53:19 +05:30
Nuwan 5932cc3d67 WIP midi and audio channel config 2023-07-07 18:53:19 +05:30
Nuwan b6868a4fbb Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2023-07-07 17:50:45 +05:30
Nuwan f1008baea8 remove alert on session recording stop 2023-07-07 17:50:12 +05:30
Nuwan 8e0e43359c WIP fixing midi configuration 2023-07-07 17:49:55 +05:30
Nuwan bc71730df4 remove alert on session recording stop 2023-07-06 10:05:21 +05:30
Nuwan 69addda196 fix Server Disconnect
add FakeJamClientProxy to wrap FakeJamClient. It accepts API calls and
sends back javascript promises.
2023-07-06 09:00:49 +05:30
Nuwan 917d8f1a8e WIP midi and audio channel config 2023-07-04 12:56:18 +05:30
Nuwan dd4f62cb07 fix js error 2023-06-14 16:55:13 +05:30
Nuwan 5d09d23809 suppress the preview recording window 2023-06-14 16:22:56 +05:30
Nuwan 01fda6b6f0 fix onSessionEnter 2023-06-02 06:48:56 +05:30
Nuwan d09baf05bb prevent session joining using web browser 2023-05-29 19:04:46 +05:30
Nuwan 03bb0f99fa fix start/stop recording dialog for session with video 2023-05-20 17:50:32 +05:30
Nuwan f4aebb44e2 fix start/stop recording dialog for session with video 2023-05-20 17:36:43 +05:30
Nuwan 7c306a13df remove debug message 2023-04-18 04:52:36 +05:30
Nuwan 6498485548 in session recording dialog box remove the video opts
with the newly invented webRTC based video recording system we can drop this options.
Only enable the video recording radio button if the backend has sent the relevant event.
2023-04-18 04:42:40 +05:30
Nuwan 0beb922db5 disable video gear setup link 2023-04-07 11:58:49 +05:30
Nuwan b8d8ca73fa sort user friend list in alphabetical order 2023-04-06 12:06:25 +05:30
Nuwan 8d816d69ed fix array iteration key/value in gear_util getChatInputs 2023-04-03 23:35:26 +05:30
Nuwan bb1c15205c fix GetDetailedOS 2023-03-18 20:09:09 +05:30
Nuwan 599e650d57 side bar search fixing
1) change the search results limit to 40
2) fix band search sql
2023-03-17 10:15:34 +05:30
Nuwan 76c56612cf fix showing build upgrade message on app startup 2023-03-16 12:26:29 +05:30
Nuwan 8d2e9d6663 fix async handler in updateSingleRecording 2023-03-14 20:26:45 +05:30
Nuwan 51f5f5ecf0 fix recording manager - not showing data 2023-03-14 13:38:55 +05:30
Nuwan dd0e24fa19 disable legacy video system 2023-02-24 23:23:10 +05:30
Nuwan aa3ac642da this includes fix for Resync button doesn't do anything 2023-02-24 17:23:19 +05:30
Nuwan 359ccfe431 fix async call order in configure audio
This error was appearing in audio gear configuration when clicking Next button in
select & test audio gear step. on this button click the program executed
an event listener on input channel check box click (programmatically) and
autoAssignToSingleInput inside the click event handler was invoked
an async call stack which was resolved before the next button click handler completed.
As a result a pop up was showing up saying "The application is no longer modifying a new profile".

This commits fixes this issue by explicitly preventing this event lister handler been executed
in this case.
2023-02-23 19:12:16 +05:30
Nuwan 4cef5acde8 new boolean parameter for TrackDeleteProfile to delete it from the Audio.ini file 2023-02-22 12:36:56 +05:30
Nuwan 172f3a654d new boolean parameter for TrackDeleteProfile to delete it from the Audio.ini file 2023-02-22 12:24:11 +05:30
Nuwan 972f9fadcc new boolean parameter for TrackDeleteProfile to delete it from the Audio.ini file 2023-02-22 11:28:37 +05:30
Nuwan 1fb6907df0 using Jquery .attr() for accessing data attributes. using .prop() here is erronious here 2023-02-22 00:16:42 +05:30
Nuwan 27d697149c fix js error when selecting framesize or sample rate settings in configure audio 2023-02-21 19:24:13 +05:30
Nuwan 60af5432ce fix frontend error when changing framesize in audio input/output configuration 2023-02-17 16:37:56 +05:30
Nuwan 19050d317b Fix configure voice chat
add missing async/await call to fetch chat inputs
2023-02-16 18:21:11 +05:30
Nuwan 80bf8119af show logs in asyncJamClient 2023-02-06 00:28:53 +05:30
Nuwan 3d26f241b4 turn off log messages in asyncJamClient 2023-02-04 03:48:19 +05:30
Nuwan b7f9ade2ea handle sendP2PMessage in asyncJamClient 2023-02-04 03:35:07 +05:30
Nuwan 4423a9c122 more async fixes related to audio interface configuration 2023-02-01 15:34:15 +05:30
Nuwan 6c56fe3af8 async calls in configure audio
adds async/await call for jamClient api calls
2023-01-31 17:58:16 +05:30
Nuwan 009ee6a6dd add GetDetailedOS in to async call array 2023-01-26 01:11:21 +05:30
Nuwan 20177f71dd Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2023-01-26 00:48:27 +05:30
Seth Call 37533c9e18 Fix odd bug in jam_track_right for current_user, and send https redirectfor download link for jamtrack 2023-01-16 13:08:40 -05:00
Nuwan 2228b91285 Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2023-01-13 11:12:09 +05:30
Seth Call dccc668d48 Fix special branch casing 2023-01-04 17:57:27 -06:00
Seth Call 16c5dbb218 Fix special branch casing 2023-01-04 17:20:21 -06:00
Nuwan 46f2fbb55f Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2023-01-04 21:42:42 +05:30
Seth Call b3d4259b09 Try removing gemfile.lock 2023-01-04 08:44:02 -06:00
Seth Call d59b83bb42 wip 2023-01-04 08:43:13 -06:00
Seth Call 7dc640fb86 debugging build 2023-01-04 08:26:39 -06:00
Seth Call cbf348564d Try to fix build 2023-01-03 14:38:20 -06:00
Seth Call e9612cbc19 special case debians for this branch 2023-01-03 08:43:48 -06:00
Nuwan 5145bfeac1 add .ruby-version to .gitignore 2022-12-23 08:18:00 +05:30
Nuwan 3349c76076 Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2022-12-16 13:51:08 +05:30
Murali Gowrisankaran bb9813ae26 Removed enumeration for open and close Url APIs 2022-12-16 02:37:30 +00:00
Nuwan bd1134b2bd Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2022-12-13 12:09:37 +05:30
Murali Gowrisankaran cc4d1575c0 Added enumerated constants for window popup APIs 2022-12-13 06:07:29 +00:00
Nuwan 033d67639c fix js error 2022-12-07 19:44:45 +05:30
Nuwan d9b4a5b8d9 fix async call issue in bands search window 2022-12-03 02:21:47 +05:30
Nuwan 87762c5933 add bugsnag error reporting to asyncJamClient 2022-11-05 04:36:05 +05:30
Nuwan 9d787351fa fixes for recording related errors 2022-11-04 18:57:09 +05:30
Nuwan f392623049 wip session recording related fixes 2022-11-03 18:54:03 +05:30
Nuwan c207b76641 debug and fixing session recording wip 2022-11-02 04:15:22 +05:30
Nuwan 2c5708b28a fix syntax error - invalid comment 2022-10-29 00:04:50 +05:30
Nuwan 2370762c51 alperbatically order JKFrontendMethods method names in asyncJamClient 2022-10-28 22:18:29 +05:30
Nuwan 3be0e25bcb add jamClient.SessionSetTrackVolumeData
this new api method is used to send session track data
over web channel to qt c++ backend
2022-10-28 22:06:34 +05:30
Nuwan 768f3d976a convert anoter few jamClient. call to async format 2022-10-28 13:12:14 +05:30
Nuwan 5487e62f5a fixes for public session creation and joining 2022-10-12 19:39:09 +05:30
Nuwan 38baea686f fixes for the errors - public session
fix errors when creating group session
and when joining group session
2022-10-07 04:16:40 +05:30
Seth Call 8c472a90a8 Fix jamtracks for local dev 2022-09-12 17:04:48 -05:00
Nuwan 73a56b2cf6 fix session metronome related functions 2022-09-07 08:49:21 +05:30
Nuwan 6486761483 Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2022-09-02 11:11:11 +05:30
Nuwan 7a7986e30a fixing audio config and session related issues 2022-09-02 11:10:51 +05:30
Seth Call 1f63aa77b4 Pass in client_id to backend websocket connection 2022-09-01 16:44:16 -05:00
Seth Call cbbfebddc9 make onMixersChanged async so that it can await internally 2022-08-17 21:57:54 -05:00
Nuwan 794d131a3e change context._.each( loops to classic for loops 2022-08-15 22:30:58 +05:30
Seth Call 98aa2adc42 Remove 2 context._.each statements combined with async 2022-08-14 17:00:38 -05:00
Nuwan 21af8446ca async call fixes for audio gear setup 2022-08-13 00:33:24 +05:30
Nuwan 8e7b9b278a fix session leave issues 2022-08-08 16:31:00 +05:30
Nuwan 1c1626df73 fix not showing Account screen content 2022-08-03 21:13:51 +05:30
Nuwan 07a00505b8 fix listing audio profiles 2022-08-03 19:08:32 +05:30
Nuwan 09e1d27c64 fix async realted errors and cleanup 2022-08-03 18:38:42 +05:30
Nuwan 11915454cb replacing context.jamClient.isNativeClient() with context.JK.isQWebEngine 2022-08-02 18:51:05 +05:30
Nuwan 8cc3a6753b Merge remote-tracking branch 'origin/promised_based_api_interation' into promised_based_api_interation 2022-08-02 13:56:23 +05:30
Nuwan c4a37daa73 adding async/await for fixing issues related to promised based pi calls 2022-08-02 09:43:01 +05:30
Seth Call 08b2de242e Create context.JK.isQWebEngine property instead of gon.isQWebEngine 2022-08-01 21:49:33 -05:00
Seth Call e19819e035 Fix step 2 of the FTUE Gear Wizard by setting some async's where needed.
Also added in gon.isQWebEngine to act as flag indicating this is the native client.
2022-08-01 21:37:35 -05:00
Nuwan b32621fe42 Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2022-07-30 08:28:34 +05:30
Nuwan 795ab8bd13 fixing errors related to gear wizard 2022-07-30 08:27:59 +05:30
Murali Gowrisankaran 2adf33e689 Removed/commented out video related frontend API calls 2022-07-28 01:12:30 +00:00
Nuwan c3bcd3b470 fixing audio gear related async errors 2022-07-27 16:22:01 +05:30
Nuwan efbe685641 Merge branch 'promised_based_api_interation' of bitbucket.org:jamkazam/jam-cloud into promised_based_api_interation 2022-07-27 11:04:04 +05:30
Nuwan 9586e0547a fixing async errors 2022-07-27 11:03:20 +05:30
Murali Gowrisankaran ffddf28a25 Fixed enum for client ID 2022-07-27 01:31:14 +00:00
Murali Gowrisankaran 57fb3ea333 Revert "Fixed enum for client ID"
This reverts commit ad61bb00cb.
2022-07-27 01:26:43 +00:00
Murali Gowrisankaran ad61bb00cb Fixed enum for client ID 2022-07-27 01:24:47 +00:00
Nuwan f732e0dad6 fixing error due to async nature of api calls 2022-07-26 23:32:36 +05:30
Murali Gowrisankaran 21ce5c237d Added method for getClientID 2022-07-12 21:27:50 +00:00
Nuwan 4b281538b2 fix errors getting after async changes
this includes errors in websocket-gateway due to blank data been
passed from web frontend to websocket routes
2022-06-16 00:02:54 +05:30
Nuwan 69cc22106d fix js error in gear_utls after changing jamClient calls to async 2022-06-02 18:00:03 +05:30
Nuwan 99d20a9869 handle the response returned from ws server for unavailable methods 2022-04-20 16:36:23 +05:30
Nuwan 43caffb85e work continues on changing jamClient calls to asynchronous 2022-04-18 19:08:02 +05:30
Nuwan cd93211406 wip promised based jamClient 2022-04-13 03:02:44 +05:30
Nuwan f05287f45a convert jamClient.* calls as promises using async/await 2022-04-07 22:31:35 +05:30
234 changed files with 14672 additions and 41201 deletions

2
.gitignore vendored
View File

@ -11,3 +11,5 @@ working.png
ruby/.rails5-gems
web/.rails5-gems
websocket-gateway/.rails5-gems
.pg_data/
.ruby-version

View File

@ -0,0 +1,181 @@
class Spacer
def self.spacer(val, row)
percentage = ((val * 100) / row.total.to_f).round(1).to_s
('%-5.5s' % percentage).gsub(' ', ' ') + '% - ' + val.to_s
end
end
=begin
select
count(id) as total,
count(first_downloaded_client_at) as downloaded,
count(first_ran_client_at) as ran_client,
count(first_certified_gear_at) as ftue,
count(first_music_session_at) as any_session,
count(first_real_music_session_at) as real_session,
count(first_good_music_session_at) as good_session,
count(first_invited_at) as invited,
count(first_friended_at) as friended,
count(first_subscribed_at) as subscribed
from users where users.created_at >= '2024-11-01' AND users.created_at < '2025-04-01'
select first_name, last_name, email
from users where users.created_at >= '2024-11-01' AND users.created_at < '2025-04-01'
AND first_music_session_at is NULL;
=end
ActiveAdmin.register_page "Jammers Subscription Cohorts" do
menu :parent => 'Reports'
content :title => "Jammers Subscription Cohorts" do
filter_type = params[:filter_type] || 'All'
filter_campaign = params[:filter_campaign]
filter_campaign_id = params[:filter_campaign_id]
filter_ad_set = params[:filter_ad_set]
filter_ad_name = params[:filter_ad_name]
campaigns = User.where("origin_utm_source ILIKE '%meta%'").distinct.pluck(:origin_utm_campaign).compact.sort
campaign_ids = User.where("origin_utm_source ILIKE '%meta%'").distinct.pluck(:origin_id).compact.sort
ad_sets = User.where("origin_utm_source ILIKE '%meta%'").distinct.pluck(:origin_term).compact.sort
ad_names = User.where("origin_utm_source ILIKE '%meta%'").distinct.pluck(:origin_content).compact.sort
div style: "margin-bottom: 20px; padding: 10px; background-color: #f4f4f4; border-radius: 4px;" do
form action: admin_jammers_subscription_cohorts_path, method: :get do
span "Source: ", style: "font-weight: bold; margin-right: 5px;"
select name: 'filter_type', onchange: 'this.form.submit()', style: "margin-right: 15px;" do
option "All", value: 'All', selected: filter_type == 'All'
option "Organic", value: 'Organic', selected: filter_type == 'Organic'
option "Advertising", value: 'Advertising', selected: filter_type == 'Advertising'
end
if filter_type == 'Advertising'
div style: "margin-top: 10px;" do
span "Campaign Name: ", style: "font-weight: bold; margin-right: 5px;"
select name: 'filter_campaign', onchange: 'this.form.submit()', style: "margin-right: 15px;" do
option "All", value: ''
option "Null", value: 'NULL', selected: filter_campaign == 'NULL'
campaigns.each do |c|
option c, value: c, selected: filter_campaign == c
end
end
span "Campaign ID: ", style: "font-weight: bold; margin-right: 5px;"
select name: 'filter_campaign_id', onchange: 'this.form.submit()', style: "margin-right: 15px;" do
option "All", value: ''
option "Null", value: 'NULL', selected: filter_campaign_id == 'NULL'
campaign_ids.each do |c|
option c, value: c, selected: filter_campaign_id == c
end
end
end
div style: "margin-top: 10px;" do
span "Ad Set: ", style: "font-weight: bold; margin-right: 5px;"
select name: 'filter_ad_set', onchange: 'this.form.submit()', style: "margin-right: 15px;" do
option "All", value: ''
option "Null", value: 'NULL', selected: filter_ad_set == 'NULL'
ad_sets.each do |c|
option c, value: c, selected: filter_ad_set == c
end
end
span "Ad Name: ", style: "font-weight: bold; margin-right: 5px;"
select name: 'filter_ad_name', onchange: 'this.form.submit()', style: "margin-right: 15px;" do
option "All", value: ''
option "Null", value: 'NULL', selected: filter_ad_name == 'NULL'
ad_names.each do |c|
option c, value: c, selected: filter_ad_name == c
end
end
end
end
noscript { input type: :submit, value: "Filter" }
end
end
h2 "Users Grouped By Month as Paying Subscribers"
query = User.select(%Q{date_trunc('month', users.created_at) as month,
count(id) as total,
count(first_downloaded_client_at) as downloaded,
count(first_ran_client_at) as ran_client,
count(first_certified_gear_at) as ftue,
count(first_music_session_at) as any_session,
count(first_real_music_session_at) as real_session,
count(first_good_music_session_at) as good_session,
count(first_invited_at) as invited,
count(first_friended_at) as friended,
count(first_subscribed_at) as subscribed,
count(first_played_jamtrack_at) as played_jamtrack
})
.joins(%Q{LEFT JOIN LATERAL (
SELECT
j.created_at
FROM
jam_track_rights as j
WHERE
j.user_id = users.id
ORDER BY
j.created_at
LIMIT 1 -- Select only that single row
) j ON TRUE })
if filter_type == 'Organic'
query = query.where("users.origin_utm_source = 'organic'")
elsif filter_type == 'Advertising'
query = query.where("users.origin_utm_source ILIKE '%meta%'")
if filter_campaign.present?
if filter_campaign == 'NULL'
query = query.where("users.origin_utm_campaign IS NULL")
else
query = query.where("users.origin_utm_campaign = ?", filter_campaign)
end
end
if filter_campaign_id.present?
if filter_campaign_id == 'NULL'
query = query.where("users.origin_id IS NULL")
else
query = query.where("users.origin_id = ?", filter_campaign_id)
end
end
if filter_ad_set.present?
if filter_ad_set == 'NULL'
query = query.where("users.origin_term IS NULL")
else
query = query.where("users.origin_term = ?", filter_ad_set)
end
end
if filter_ad_name.present?
if filter_ad_name == 'NULL'
query = query.where("users.origin_content IS NULL")
else
query = query.where("users.origin_content = ?", filter_ad_name)
end
end
end
table_for query.group("date_trunc('month', users.created_at)")
.where("j.created_at IS NULL OR (j.created_at - users.created_at) >= INTERVAL '2 hours'")
.order("date_trunc('month', users.created_at) DESC") do |row|
column "Month", Proc.new { |user| user.month.strftime('%B %Y') }
column "Total", :total
column "Subscribed", Proc.new { |user| raw(Spacer.spacer(user.subscribed, user)) }
column "Downloaded", Proc.new { |user| raw(Spacer.spacer(user.downloaded, user)) }
column "Ran Client", Proc.new { |user| raw(Spacer.spacer(user.ran_client, user)) }
column "FTUE", Proc.new { |user| raw(Spacer.spacer(user.ftue, user)) }
column "Any Session", Proc.new { |user| raw(Spacer.spacer(user.any_session, user)) }
column "2+ Session", Proc.new { |user| raw(Spacer.spacer(user.real_session, user)) }
column "Good Session", Proc.new { |user| raw(Spacer.spacer(user.good_session, user)) }
column "Invited", Proc.new { |user| raw(Spacer.spacer(user.invited, user)) }
column "Friended", Proc.new { |user| raw(Spacer.spacer(user.friended, user)) }
column "Played JT", Proc.new { |user| raw(Spacer.spacer(user.played_jamtrack, user)) }
end
end
end

View File

@ -131,7 +131,7 @@ module JamAdmin
config.email_smtp_starttls_auto = true
config.verify_email_enabled = false
config.musician_count = '200,000+'
config.musician_count = '300,000+'
config.facebook_app_id = ENV['FACEBOOK_APP_ID'] || '468555793186398'
config.facebook_app_secret = ENV['FACEBOOK_APP_SECRET'] || '546a5b253972f3e2e8b36d9a3dd5a06e'

View File

@ -1,5 +0,0 @@
<atlassian-ide-plugin>
<project-configuration id="1">
<servers id="2" />
</project-configuration>
</atlassian-ide-plugin>

2
build
View File

@ -61,7 +61,7 @@ if [ ! -z "$PACKAGE" ]; then
GEM_SERVER=http://localhost:9000/gems
# if still going, then push all debs up
if [[ "$GIT_BRANCH" == *develop* || "$GIT_BRANCH" == *master* || "$GIT_BRANCH" == *release* || "$GIT_BRANCH" == *feature* || "$GIT_BRANCH" == *hotfix* ]]; then
if [[ "$GIT_BRANCH" == *develop* || "$GIT_BRANCH" == *master* || "$GIT_BRANCH" == *release* || "$GIT_BRANCH" == *feature* || "$GIT_BRANCH" == *hotfix* || "$GIT_BRANCH" == *promised_based_api_interation* ]]; then
echo ""
echo "PUSHING WEB"

View File

@ -1,4 +1,4 @@
HOST=beta.jamkazam.com
HOST=www.jamkazam.com
PORT=4000
REACT_APP_ORIGIN=jamkazam.com
REACT_APP_LEGACY_BASE_URL=https://www.jamkazam.com

View File

@ -0,0 +1,161 @@
import React, { useRef, useState, useEffect } from 'react';
import { Form, FormGroup, Input, Label, Card, CardBody, Button, Row, Col } from 'reactstrap';
import FalconCardHeader from '../common/FalconCardHeader';
import JKTooltip from '../common/JKTooltip';
import { useTranslation } from 'react-i18next';
import { useAuth } from '../../context/UserAuth';
import JKFriendsAutoComplete from '../people/JKFriendsAutoComplete';
import JKSessionInviteesChips from '../people/JKSessionInviteesChips';
import { getFriends } from '../../helpers/rest';
const JKNewMusicSession = () => {
const { currentUser } = useAuth();
const { t } = useTranslation();
const [friends, setFriends] = useState([]);
const [isFriendsFetched, setIsFriendsFetched] = useState(false)
const [description, setDescription] = useState("")
const [invitees, setInvitees] = useState([]);
const [privacy, setPrivacy] = useState("1");
useEffect(() => {
fetchFriends();
}, []);
useEffect(() => {
if(isFriendsFetched){
populateFormDataFromLocalStorage()
}
}, [isFriendsFetched])
const fetchFriends = () => {
getFriends(currentUser.id)
.then(resp => {
if (resp.ok) {
return resp.json();
}
})
.then(data => {
console.log('friends = ', data)
setFriends(data);
setIsFriendsFetched(true);
});
}
const populateFormDataFromLocalStorage = () => {
try {
const formData = localStorage.getItem('formData');
if(formData){
const formDataItems = JSON.parse(formData);
setDescription(formDataItems['description']);
setPrivacy(formDataItems['privacy']);
const inviteeIds = formDataItems['inviteeIds'];
const invitees = friends.filter(f => inviteeIds.includes(f.id));
updateSessionInvitations(invitees);
}
} catch (error) {
console.error('localStorage is not available', error)
}
}
const handleSubmit = event => {
event.preventDefault();
const formData = new FormData(event.target);
const payload = {
privacy: formData.get('privacy'),
description: formData.get('description'),
inviteeIds: invitees.map(i => i.id)
};
console.log(payload); //TODO: handle payload
try {
//store this payload in localstorage.
localStorage.setItem('formData', JSON.stringify(payload))
} catch (error) {
console.error("localStorage is not available", error);
}
//if JamKazam application is not upload on the local computer
//Show a modal dialog for the user
//TODO: need a new backend api to start the session with the formdata
};
const handleOnSelect = submittedItems => {
updateSessionInvitations(submittedItems)
};
const updateSessionInvitations = (submittedInvitees) => {
const updatedInvitees = Array.from(new Set([...invitees, ...submittedInvitees]));
setInvitees(updatedInvitees);
const friendIds = submittedInvitees.map(si => si.id)
const updatedFriends = friends.filter(f => !friendIds.includes(f.id));
setFriends(updatedFriends);
}
const removeInvitee = invitee => {
const updatedInvitees = invitees.filter(i => i.id !== invitee.id);
setInvitees(updatedInvitees);
const updatedFriends = [...friends, invitee];
setFriends(updatedFriends);
};
return (
<div>
<Card>
<FalconCardHeader title={t('new.page_title', { ns: 'sessions' })} titleClass="font-weight-bold" />
<CardBody className="pt-0">
<Row>
<Col>
<Form onSubmit={handleSubmit}>
<FormGroup className="mb-3">
<Label>
{t('new.privacy', { ns: 'sessions' })}{' '}
<JKTooltip title={t('new.privacy_help', { ns: 'sessions' })} />
</Label>
<Input type="select" aria-label="Session Privacy" name="privacy" value={privacy} onChange={(e) => setPrivacy(e.target.value)} data-testid="session-privacy">
<option value="1">{t('new.privacy_opt_public', { ns: 'sessions' })}</option>
<option value="2">{t('new.privacy_opt_private_invite', { ns: 'sessions' })}</option>
<option value="3">{t('new.privacy_opt_private_approve', { ns: 'sessions' })}</option>
</Input>
</FormGroup>
<FormGroup className="mb-3">
<Label>
{t('new.invitations', { ns: 'sessions' })}{' '}
<JKTooltip title={t('new.invitations_help', { ns: 'sessions' })} />
</Label>
<JKFriendsAutoComplete friends={friends} onSelect={handleOnSelect} />
{ invitees.length > 0 &&
<JKSessionInviteesChips invitees={invitees} removeInvitee={removeInvitee} />
}
</FormGroup>
<FormGroup className="mb-3">
<Label>
{t('new.description', { ns: 'sessions' })}{' '}
<JKTooltip title={t('new.description_help', { ns: 'sessions' })} />
</Label>
<Input
value={description}
onChange={(e) => setDescription(e.target.value)}
name="description"
type="textarea"
data-testid="session-description"
placeholder={t('new.description_placeholder', { ns: 'sessions' })}
/>
</FormGroup>
<FormGroup className="mb-3">
<Button color="primary" data-testid="btn-create-session">{t('new.create_session', { ns: 'sessions' })}</Button>
</FormGroup>
</Form>
</Col>
<Col />
</Row>
</CardBody>
</Card>
</div>
);
};
export default JKNewMusicSession;

View File

@ -0,0 +1,98 @@
/**
* meta_tracking.js
* A standalone module to capture and persist Meta attribution signals (fbclid, _fbp) in cookies.
*
* Logic adapted from web/app/assets/javascripts/meta_tracking.js for React environment.
* - Checks URL for `fbclid` and sets `_fbc` cookie.
* - Checks for `_fbp` cookie; if missing, generates and sets it.
*/
const MetaTracking = {
init: function () {
const location = window.location;
this.handleFbc(location.search);
this.handleUtm(location.search);
this.handleFbp();
},
// 1. Parsing and storing _fbc (Click ID)
handleFbc: function (searchParams) {
const fbclid = this.getQueryParam('fbclid', searchParams);
if (fbclid) {
const version = 'fb';
const subdomainIndex = 1; // 1 = example.com
const creationTime = new Date().getTime(); // Unix timestamp in ms
// Format: fb.1.timestamp.id
const fbcValue = `${version}.${subdomainIndex}.${creationTime}.${fbclid}`;
this.setCookie('_fbc', fbcValue, 90);
}
},
handleUtm: function (searchParams) {
if (!searchParams) return;
const query = searchParams.substring(1);
const vars = query.split('&');
vars.forEach(v => {
const pair = v.split('=');
if (pair.length === 2) {
const key = decodeURIComponent(pair[0]);
const value = decodeURIComponent(pair[1]);
if (key.indexOf('utm_') === 0) {
this.setCookie(key, value, 90);
}
}
});
},
// 2. Handling _fbp (Browser ID)
handleFbp: function () {
if (!this.getCookie('_fbp')) {
const version = 'fb';
const subdomainIndex = 1;
const creationTime = new Date().getTime();
const randomInt = Math.floor(Math.random() * 10000000000); // 10-digit random number
// Format: fb.1.timestamp.randomDigits
const fbpValue = `${version}.${subdomainIndex}.${creationTime}.${randomInt}`;
this.setCookie('_fbp', fbpValue, 90);
}
},
// Helper: Get query param by name
getQueryParam: function (name, search) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
const regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
const results = regex.exec(search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
},
// Helper: Set cookie
setCookie: function (name, value, days) {
let expires = "";
if (days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
// Ensure path is root and domain is included if needed (defaults to current host)
document.cookie = name + "=" + (value || "") + expires + "; path=/";
},
// Helper: Get cookie
getCookie: function (name) {
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
};
export default MetaTracking;

View File

@ -1,4 +1,4 @@
import React, {useEffect} from 'react';
import React, { useEffect } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { toast, ToastContainer } from 'react-toastify';
import { CloseButton, Fade } from '../components/common/Toast';
@ -8,11 +8,13 @@ import ErrorLayout from './ErrorLayout';
import BuildMeta from "./JKBuildMeta";
import loadable from '@loadable/component';
import MetaTracking from "../helpers/MetaTracking";
const AuthBasicLayout = loadable(() => import('./JKAuthBasicLayout'));
const Layout = () => {
useEffect(() => {
AuthBasicLayout.preload();
MetaTracking.init();
}, []);
return (

View File

@ -210,8 +210,8 @@ end
def jk_select(text, select)
# the approach here is to find the hidden select element, and work way back up to the elements that need to be interacted with
find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown easydropdown")]').trigger(:click)
find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown-wrapper") and contains(@class, "easydropdown-wrapper") and contains(@class, "open")]').find('li', text: text).trigger(:click)
find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown easydropdown")]').click()
find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown-wrapper") and contains(@class, "easydropdown-wrapper") and contains(@class, "open")]').find('span', text: text).click()
# works, but is 'cheating' because of visible = false
#select(genre, :from => 'genres', :visible => false)

View File

@ -13,4 +13,4 @@ RUBY VERSION
ruby 2.4.1p111
BUNDLED WITH
1.17.3
2.3.17

View File

@ -8,6 +8,8 @@ RUBY_OUT=$TARGET/ruby
command -v "bundle" || { echo >&2 "bundle is required but not installed. Skipping ruby protocol buffers."; exit 0; }
# creates a bin folder with 'rprotoc' command inside
#echo "skipping creation of binstubs as it breaks bin/ruby-protoc invocation below"
rm Gemfile.lock
bundle install --binstubs
# die on error at this point

View File

@ -184,7 +184,7 @@ CREATE FUNCTION public.discard_scores(keep integer) RETURNS void
CREATE FUNCTION public.generate_scores_dataset() RETURNS void
LANGUAGE plpgsql STRICT
AS $$ BEGIN delete from GeoIPLocations; insert into GeoIPLocations (locId, countryCode, region, city, postalCode, latitude, longitude, metroCode, areaCode) values (17192,'US','TX','Austin','78749',30.2076,-97.8587,635,'512'), (667,'US','TX','Dallas','75207',32.7825,-96.8207,623,'214'), (30350,'US','TX','Houston','77001',29.7633,-95.3633,618,'713'), (31423,'US','CO','Denver','80201',39.7392,-104.9847,751,'303'), (1807,'US','TX','San Antonio','78201',29.4713,-98.5353,641,'210'), (23565,'US','FL','Miami','33101',25.7743,-80.1937,528,'305'), (11704,'US','FL','Tampa','33601',27.9475,-82.4584,539,'813'), (26424,'US','MA','Boston','02101',42.3584,-71.0598,506,'617'), (5059,'US','ME','Portland','04101',43.6589,-70.2615,500,'207'), (2739,'US','OR','Portland','97201',45.5073,-122.6932,820,'503'), (1539,'US','WA','Seattle','98101',47.6103,-122.3341,819,'206'), (2720,'US','CA','Mountain View','94040',37.3845,-122.0881,807,'650'), (154078,'US','AR','Mountain View','72560',35.8732,-92.0717,693,'870'), (3964,'US','CA','Barstow','92311',34.9701,-116.9929,803,'760'), (14447,'US','OK','Tulsa','74101',36.154,-95.9928,671,'918'), (162129,'US','TN','Memphis','37501',35.1693,-89.9904,640,'713'); delete from GeoIPBlocks; insert into GeoIPBlocks (beginIp, endIp, locId) values (x'00000000'::bigint,x'0FFFFFFF'::bigint,17192), (x'10000000'::bigint,x'1FFFFFFF'::bigint,667), (x'20000000'::bigint,x'2FFFFFFF'::bigint,30350), (x'30000000'::bigint,x'3FFFFFFF'::bigint,31423), (x'40000000'::bigint,x'4FFFFFFF'::bigint,1807), (x'50000000'::bigint,x'5FFFFFFF'::bigint,23565), (x'60000000'::bigint,x'6FFFFFFF'::bigint,11704), (x'70000000'::bigint,x'7FFFFFFF'::bigint,26424), (x'80000000'::bigint,x'8FFFFFFF'::bigint,5059), (x'90000000'::bigint,x'9FFFFFFF'::bigint,2739), (x'A0000000'::bigint,x'AFFFFFFF'::bigint,1539), (x'B0000000'::bigint,x'BFFFFFFF'::bigint,2720), (x'C0000000'::bigint,x'CFFFFFFF'::bigint,154078), (x'D0000000'::bigint,x'DFFFFFFF'::bigint,3964), (x'E0000000'::bigint,x'EFFFFFFF'::bigint,14447), (x'F0000000'::bigint,x'FFFEFFFF'::bigint,162129); delete from GeoIPISP; insert into GeoIPISP values (x'00000000'::bigint,x'0FFFFFFF'::bigint,'Intergalactic Boogie'), (x'10000000'::bigint,x'1FFFFFFF'::bigint,'Powerful Pipes'), (x'20000000'::bigint,x'2FFFFFFF'::bigint,'Powerful Pipes'), (x'30000000'::bigint,x'3FFFFFFF'::bigint,'Intergalactic Boogie'), (x'40000000'::bigint,x'4FFFFFFF'::bigint,'Tangled Webs'), (x'50000000'::bigint,x'5FFFFFFF'::bigint,'Tangled Webs'), (x'60000000'::bigint,x'6FFFFFFF'::bigint,'Powerful Pipes'), (x'70000000'::bigint,x'7FFFFFFF'::bigint,'Intergalactic Boogie'), (x'80000000'::bigint,x'8FFFFFFF'::bigint,'Greasy Lightning'), (x'90000000'::bigint,x'9FFFFFFF'::bigint,'Powerful Pipes'), (x'A0000000'::bigint,x'AFFFFFFF'::bigint,'Intergalactic Boogie'), (x'B0000000'::bigint,x'BFFFFFFF'::bigint,'Tangled Webs'), (x'C0000000'::bigint,x'CFFFFFFF'::bigint,'Greasy Lightning'), (x'D0000000'::bigint,x'DFFFFFFF'::bigint,'Tangled Webs'), (x'E0000000'::bigint,x'EFFFFFFF'::bigint,'Intergalactic Boogie'), (x'F0000000'::bigint,x'FFFEFFFF'::bigint,'Powerful Pipes'); DELETE FROM jamcompany; ALTER SEQUENCE jamcompany_coid_seq RESTART WITH 1; INSERT INTO jamcompany (company) SELECT DISTINCT company FROM geoipisp ORDER BY company; DELETE FROM jamisp; INSERT INTO jamisp (beginip, endip, coid) SELECT x.beginip, x.endip, y.coid FROM geoipisp x, jamcompany y WHERE x.company = y.company; IF EXISTS( SELECT * FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'cities') THEN DELETE FROM cities; INSERT INTO cities (city, region, countrycode) select distinct city, region, countrycode from geoiplocations where length(city) > 0 and length(countrycode) > 0; DELETE FROM regions; INSERT INTO regions (region, regionname, countrycode) select distinct region, region, countrycode from cities; DELETE FROM countries; INSERT INTO countries (countrycode, countryname) select distinct countrycode, countrycode from regions; END IF; RETURN; END; $$;
AS $$ BEGIN delete from GeoIPLocations; insert into GeoIPLocations (locId, countryCode, region, city, postalCode, latitude, longitude, metroCode, areaCode) values (17192,'US','TX','Austin','78749',30.2076,-97.8587,635,'512'), (667,'US','TX','Dallas','75207',32.7825,-96.8207,623,'214'), (30350,'US','TX','Houston','77001',29.7633,-95.3633,618,'713'), (31423,'US','CO','Denver','80201',39.7392,-104.9847,751,'303'), (1807,'US','TX','San Antonio','78201',29.4713,-98.5353,641,'210'), (23565,'US','FL','Miami','33101',25.7743,-80.1937,528,'305'), (11704,'US','FL','Tampa','33601',27.9475,-82.4584,539,'813'), (26424,'US','MA','Boston','02101',42.3584,-71.0598,506,'617'), (5059,'US','ME','Portland','04101',43.6589,-70.2615,500,'207'), (2739,'US','OR','Portland','97201',45.5073,-122.6932,820,'503'), (1539,'US','WA','Seattle','98101',47.6103,-122.3341,819,'206'), (2720,'US','CA','Mountain View','94040',37.3845,-122.0881,807,'650'), (154078,'US','AR','Mountain View','72560',35.8732,-92.0717,693,'870'), (3964,'US','CA','Barstow','92311',34.9701,-116.9929,803,'760'), (14447,'US','OK','Tulsa','74101',36.154,-95.9928,671,'918'), (162129,'US','TN','Memphis','37501',35.1693,-89.9904,640,'713'); delete from GeoIPBlocks; insert into GeoIPBlocks (beginIp, endIp, locId) values (x'00000000'::bigint,x'0FFFFFFF'::bigint,17192), (x'10000000'::bigint,x'1FFFFFFF'::bigint,667), (x'20000000'::bigint,x'2FFFFFFF'::bigint,30350), (x'30000000'::bigint,x'3FFFFFFF'::bigint,31423), (x'40000000'::bigint,x'4FFFFFFF'::bigint,1807), (x'50000000'::bigint,x'5FFFFFFF'::bigint,23565), (x'60000000'::bigint,x'6FFFFFFF'::bigint,11704), (x'70000000'::bigint,x'7FFFFFFF'::bigint,26424), (x'80000000'::bigint,x'8FFFFFFF'::bigint,5059), (x'90000000'::bigint,x'9FFFFFFF'::bigint,2739), (x'A0000000'::bigint,x'AFFFFFFF'::bigint,1539), (x'B0000000'::bigint,x'BFFFFFFF'::bigint,2720), (x'C0000000'::bigint,x'CFFFFFFF'::bigint,154078), (x'D0000000'::bigint,x'DFFFFFFF'::bigint,3964), (x'E0000000'::bigint,x'EFFFFFFF'::bigint,14447), (x'F0000000'::bigint,x'FFFEFFFF'::bigint,162129); delete from GeoIPISP; insert into GeoIPISP values (x'00000000'::bigint,x'0FFFFFFF'::bigint,'Intergalactic Boogie'), (x'10000000'::bigint,x'1FFFFFFF'::bigint,'Powerful Pipes'), (x'20000000'::bigint,x'2FFFFFFF'::bigint,'Powerful Pipes'), (x'30000000'::bigint,x'3FFFFFFF'::bigint,'Intergalactic Boogie'), (x'40000000'::bigint,x'4FFFFFFF'::bigint,'Tangled Webs'), (x'50000000'::bigint,x'5FFFFFFF'::bigint,'Tangled Webs'), (x'60000000'::bigint,x'6FFFFFFF'::bigint,'Powerful Pipes'), (x'70000000'::bigint,x'7FFFFFFF'::bigint,'Intergalactic Boogie'), (x'80000000'::bigint,x'8FFFFFFF'::bigint,'Greasy Lightning'), (x'90000000'::bigint,x'9FFFFFFF'::bigint,'Powerful Pipes'), (x'A0000000'::bigint,x'AFFFFFFF'::bigint,'Intergalactic Boogie'), (x'B0000000'::bigint,x'BFFFFFFF'::bigint,'Tangled Webs'), (x'C0000000'::bigint,x'CFFFFFFF'::bigint,'Greasy Lightning'), (x'D0000000'::bigint,x'DFFFFFFF'::bigint,'Tangled Webs'), (x'E0000000'::bigint,x'EFFFFFFF'::bigint,'Intergalactic Boogie'), (x'F0000000'::bigint,x'FFFEFFFF'::bigint,'Powerful Pipes'); DELETE FROM jamcompany; ALTER SEQUENCE jamcompany_coid_seq RESTART WITH 1; INSERT INTO jamcompany (company) SELECT DISTINCT company FROM geoipisp ORDER BY company; DELETE FROM jamisp; INSERT INTO jamisp (beginip, endip, coid) SELECT x.beginip, x.endip, y.coid FROM geoipisp x, jamcompany y WHERE x.company = y.company; IF EXISTS( SELECT * FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'cities') THEN DELETE FROM cities; INSERT INTO cities (city, region, countrycode) select distinct city, region, countrycode from geoiplocations where length(city) > 0 and length(countrycode) > 0; DELETE FROM regions; INSERT INTO regions (region, regionname, countrycode) select distinct region, region, countrycode from cities; DELETE FROM countries; INSERT INTO countries (countrycode, countryname) select distinct countrycode, countrycode from regions; update countries set countryname='United States' where countrycode='US'; END IF; RETURN; END; $$;
--
@ -10279,7 +10279,7 @@ SELECT pg_catalog.setval('public.connections_client_id_int_seq', 1, false);
-- Data for Name: countries; Type: TABLE DATA; Schema: public; Owner: postgres
--
INSERT INTO public.countries VALUES ('US', NULL);
INSERT INTO public.countries VALUES ('US', 'United States');
--
@ -11019,17 +11019,17 @@ SELECT pg_catalog.setval('public.partner_key_sequence', 10000, false);
-- Data for Name: regions; Type: TABLE DATA; Schema: public; Owner: postgres
--
INSERT INTO public.regions VALUES ('TN', NULL, 'US');
INSERT INTO public.regions VALUES ('ME', NULL, 'US');
INSERT INTO public.regions VALUES ('MA', NULL, 'US');
INSERT INTO public.regions VALUES ('TX', NULL, 'US');
INSERT INTO public.regions VALUES ('OK', NULL, 'US');
INSERT INTO public.regions VALUES ('WA', NULL, 'US');
INSERT INTO public.regions VALUES ('CO', NULL, 'US');
INSERT INTO public.regions VALUES ('CA', NULL, 'US');
INSERT INTO public.regions VALUES ('AR', NULL, 'US');
INSERT INTO public.regions VALUES ('FL', NULL, 'US');
INSERT INTO public.regions VALUES ('OR', NULL, 'US');
INSERT INTO public.regions VALUES ('TN', 'Tennessee', 'US');
INSERT INTO public.regions VALUES ('ME', 'Maine', 'US');
INSERT INTO public.regions VALUES ('MA', 'Massachusetts', 'US');
INSERT INTO public.regions VALUES ('TX', 'Texas', 'US');
INSERT INTO public.regions VALUES ('OK', 'Oklahoma', 'US');
INSERT INTO public.regions VALUES ('WA', 'Washington', 'US');
INSERT INTO public.regions VALUES ('CO', 'Colorado', 'US');
INSERT INTO public.regions VALUES ('CA', 'California', 'US');
INSERT INTO public.regions VALUES ('AR', 'Arkansas', 'US');
INSERT INTO public.regions VALUES ('FL', 'Florida', 'US');
INSERT INTO public.regions VALUES ('OR', 'Oregon', 'US');
--

View File

@ -0,0 +1,31 @@
class AddExtendedUtmToUsers < ActiveRecord::Migration[5.0]
def up
execute <<-SQL
ALTER TABLE users ADD COLUMN origin_id character varying;
ALTER TABLE users ADD COLUMN origin_term character varying;
ALTER TABLE users ADD COLUMN origin_content character varying;
CREATE INDEX index_users_on_origin_id ON users (origin_id);
CREATE INDEX index_users_on_origin_term ON users (origin_term);
CREATE INDEX index_users_on_origin_content ON users (origin_content);
CREATE INDEX index_users_on_origin_utm_source ON users (origin_utm_source);
CREATE INDEX index_users_on_origin_utm_medium ON users (origin_utm_medium);
SQL
end
def down
execute <<-SQL
DROP INDEX IF EXISTS index_users_on_origin_utm_medium;
DROP INDEX IF EXISTS index_users_on_origin_utm_source;
DROP INDEX IF EXISTS index_users_on_origin_content;
DROP INDEX IF EXISTS index_users_on_origin_term;
DROP INDEX IF EXISTS index_users_on_origin_id;
ALTER TABLE users DROP COLUMN IF EXISTS origin_content;
ALTER TABLE users DROP COLUMN IF EXISTS origin_term;
ALTER TABLE users DROP COLUMN IF EXISTS origin_id;
SQL
end
end

View File

@ -55,6 +55,7 @@ require "jam_ruby/lib/em_helper"
require "jam_ruby/lib/nav"
require "jam_ruby/lib/html_sanitize"
require "jam_ruby/lib/guitar_center"
require "jam_ruby/lib/capi_transmitter"
require "jam_ruby/subscription_definitions"
require "jam_ruby/resque/resque_jam_error"
require "jam_ruby/resque/resque_hooks"

View File

@ -478,6 +478,7 @@ SQL
end
if tracks_changed
music_session.active_music_session.tick_track_changes
Notification.send_tracks_changed(music_session.active_music_session)
end
@ -529,6 +530,7 @@ SQL
end
if send_tracks_changed
music_session.active_music_session.tick_track_changes
Notification.send_tracks_changed(music_session.active_music_session)
end
end

View File

@ -32,5 +32,4 @@ INSERT INTO regions (region, countrycode) SELECT DISTINCT region, countrycode FR
DELETE FROM countries;
INSERT INTO countries (countrycode) SELECT DISTINCT countrycode FROM regions;
VACUUM ANALYSE;

View File

@ -1875,9 +1875,9 @@ module JamRuby
mp3_48000 = File.join(tmp_dir, File.basename(basename, ".wav") + "-48000.mp3")
aac_48000 = File.join(tmp_dir, File.basename(basename, ".wav") + "-48000.aac")
`ffmpeg -i "#{wav_file}" -ar 48000 -ab 192k "#{mp3_48000}"`
`#{APP_CONFIG.ffmpeg_path} -i "#{wav_file}" -ar 48000 -ab 192k "#{mp3_48000}"`
`ffmpeg -i "#{wav_file}" -c:a libfdk_aac -b:a 192k "#{aac_48000}"`
`#{APP_CONFIG.ffmpeg_path} -i "#{wav_file}" -c:a libfdk_aac -b:a 192k "#{aac_48000}"`
# upload the new ogg files to s3
@@log.debug("uploading mp3 48000 to #{mp3_48000_s3_path}")
@ -1971,9 +1971,9 @@ module JamRuby
mp3_48000 = File.join(tmp_dir, File.basename(basename, ".wav") + "-48000.mp3")
aac_48000 = File.join(tmp_dir, File.basename(basename, ".wav") + "-48000.aac")
`ffmpeg -i "#{wav_file}" -ar 48000 -ab 192k "#{mp3_48000}"`
`#{APP_CONFIG.ffmpeg_path} -i "#{wav_file}" -ar 48000 -ab 192k "#{mp3_48000}"`
`ffmpeg -i "#{wav_file}" -c:a libfdk_aac -b:a 192k "#{aac_48000}"`
`#{APP_CONFIG.ffmpeg_path} -i "#{wav_file}" -c:a libfdk_aac -b:a 192k "#{aac_48000}"`
# upload the new ogg files to s3
@@log.debug("uploading mp3 48000 to #{mp3_48000_s3_path}")
@ -2710,7 +2710,7 @@ module JamRuby
click_wav = File.join(tmp_dir, 'Click.wav')
song_storage_manager.download(base_dir + '/Click.mp3', click_mp3)
`ffmpeg -i "#{click_mp3}" "#{click_wav}"`
`#{APP_CONFIG.ffmpeg_path} -i "#{click_mp3}" "#{click_wav}"`
song_storage_manager.upload(base_dir + '/Click.wav', click_wav)
importer.finish("success", nil)
@ -3136,6 +3136,10 @@ module JamRuby
count = 0
iterate_song_storage do |metadata, metalocation|
if metadata[:original_artist] != "AC DC"
@@log.info("skipping #{metadata[:original_artist]}")
next
end
next if metadata.nil? && (is_tency_storage? || is_paris_storage?)
importer = synchronize_from_meta(metalocation, options)

View File

@ -56,7 +56,7 @@ module JamRuby
part = jam_track_track.track_type == 'Click' ? 'ClickTrack' : jam_track_track.part
jam_file_opts << " -i #{Shellwords.escape("#{track_filename}+#{part}")}"
end
#puts "LS + " + `ls -la '#{tmp_dir}'`
# puts "LS + " + `ls -la '#{tmp_dir}'`
sku=jam_track.id
title=jam_track.name
@ -68,7 +68,7 @@ module JamRuby
step = bump_step(jam_track_right, step)
# From http://stackoverflow.com/questions/690151/getting-output-of-system-calls-in-ruby/5970819#5970819:
cli = "python #{py_file} -D -k #{sku} -p #{Shellwords.escape(tmp_dir)}/pkey.pem -s #{Shellwords.escape(tmp_dir)}/skey.pem #{jam_file_opts} -o #{Shellwords.escape(output_jkz)} -t #{Shellwords.escape(title)} -V #{Shellwords.escape(version)}"
cli = "python2 #{py_file} -D -k #{sku} -p #{Shellwords.escape(tmp_dir)}/pkey.pem -s #{Shellwords.escape(tmp_dir)}/skey.pem #{jam_file_opts} -o #{Shellwords.escape(output_jkz)} -t #{Shellwords.escape(title)} -V #{Shellwords.escape(version)}"
Open3.popen3(cli) do |stdin, stdout, stderr, wait_thr|
pid = wait_thr.pid
exit_status = wait_thr.value

View File

@ -34,7 +34,7 @@ module JamRuby
@@log.info "Executing python source in #{py_file}, outputting to #{output_json})"
# From http://stackoverflow.com/questions/690151/getting-output-of-system-calls-in-ruby/5970819#5970819:
cli = "python #{py_file} -i '#{input_text}' -o '#{output_json}'"
cli = "python2 #{py_file} -i '#{input_text}' -o '#{output_json}'"
Open3.popen3(cli) do |stdin, stdout, stderr, wait_thr|
pid = wait_thr.pid
exit_status = wait_thr.value

View File

@ -0,0 +1,81 @@
require 'net/http'
require 'uri'
require 'json'
class CapiTransmitter
def self.send_event(event_name, user, custom_data = {}, event_source_url = nil)
begin
pixel_id = APP_CONFIG.facebook_pixel_id
access_token = APP_CONFIG.facebook_access_token
if pixel_id.blank? || access_token.blank?
puts("CapiTransmitter: Missing Facebook Pixel ID or Access Token. Skipping event #{event_name}.")
return
end
# Construct the User Data object
user_data = {
# client_ip_address: user.current_sign_in_ip,
# client_user_agent: user.user_agent # Note: User model might not have user_agent stored directly, might need to pass it or rely on what's available
}
if !user.facebook_click_id.present? ||
!APP_CONFIG.facebook_ad_source.include?(user.origin_utm_source)
return
end
# Enhance user data with hashed PII if available
# Facebook requires SHA256 hashing for PII
# For now, we rely on click_id and browser_id as primary keys if available
user_data[:fbc] = user.facebook_click_id if user.facebook_click_id.present?
user_data[:fbp] = user.facebook_browser_id if user.facebook_browser_id.present?
# If we have email/phone, we should hash them. But for now, let's stick to the IDs.
# Ideally we should hash email if we have it.
if user.email.present?
user_data[:em] = Digest::SHA256.hexdigest(user.email.downcase)
end
payload = {
data: [
{
event_name: event_name,
event_time: Time.now.to_i,
action_source: "website",
user_data: user_data,
custom_data: custom_data,
event_source_url: event_source_url
}
]
}
url = URI.parse("https://graph.facebook.com/v19.0/#{pixel_id}/events?access_token=#{access_token}")
http = Net::HTTP.new(url.host, url.port)
if APP_CONFIG.facebook_conversion_api_tls == false
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
else
http.use_ssl = true
end
request = Net::HTTP::Post.new(url.request_uri)
request['Content-Type'] = 'application/json'
request.body = payload.to_json
response = http.request(request)
if response.code.to_i >= 400
puts("CapiTransmitter Error: #{response.code} - #{response.body}")
else
puts("CapiTransmitter Success: #{event_name} sent for User #{user.id}")
end
rescue => e
puts("CapiTransmitter Exception: #{e.message}")
puts(e.backtrace.join("\n"))
end
end
end

View File

@ -863,6 +863,10 @@ module JamRuby
self.save!(:validate => false)
end
def in_session?(user)
self.users.exists?(user.id)
end
def connected_participant_count
Connection.where(:music_session_id => self.id,
:aasm_state => Connection::CONNECT_STATE.to_s,

View File

@ -11,4 +11,4 @@ module JamRuby
Ars.where(active: true, beta: beta).where('ip is not NULL').where("ip != ''").all
end
end
end
end

View File

@ -3,8 +3,17 @@ module JamRuby
DEFAULT_ENVIRONMENT = 'public'
CLIENT_PREFIX = 'JamClient'
CLIENT_PREFIX_MODERN = 'JamClientModern'
PRODUCTS = ["#{CLIENT_PREFIX}/Win32", "#{CLIENT_PREFIX}/MacOSX", "#{CLIENT_PREFIX}/JamBlaster", "#{CLIENT_PREFIX}/JamBlasterClient"]
PRODUCTS = [
"#{CLIENT_PREFIX}/Win32",
"#{CLIENT_PREFIX}/MacOSX",
"#{CLIENT_PREFIX}/JamBlaster",
"#{CLIENT_PREFIX}/JamBlasterClient",
"#{CLIENT_PREFIX_MODERN}/Win32",
"#{CLIENT_PREFIX_MODERN}/MacOSX-Intel",
"#{CLIENT_PREFIX_MODERN}/MacOSX-M"
]
self.primary_key = 'id'
attr_accessible :version, :uri, :sha1, :environment, :product, as: :admin
@ -34,8 +43,8 @@ module JamRuby
Notification.send_client_update(product, version, determine_url, size)
end
def self.find_client_by_os(os, environment=DEFAULT_ENVIRONMENT)
ArtifactUpdate.find_by_product_and_environment("#{CLIENT_PREFIX}/#{os}", environment)
def self.find_client_by_os(product, os, environment=DEFAULT_ENVIRONMENT)
ArtifactUpdate.find_by_product_and_environment("#{product}/#{os}", environment)
end
def determine_url

View File

@ -23,8 +23,11 @@ module JamRuby
validate :validate_photo_info
validate :require_at_least_one_genre, :unless => :skip_genre_validation
validate :limit_max_genres
validates_numericality_of :hourly_rate, greater_than:0, less_than:100000, :if => :paid_gigs
validates_numericality_of :gig_minimum, greater_than:0, less_than:200000, :if => :paid_gigs
#validates_numericality_of :hourly_rate, greater_than:0, less_than:100000, :if => :paid_gigs, allow_blank: true
validates :hourly_rate, numericality: { greater_than:0, less_than:100000 }, :if => :paid_gigs
#validates_numericality_of :gig_minimum, greater_than:0, less_than:200000, :if => :paid_gigs, allow_blank: true
validates :gig_minimum, numericality: { greater_than:0, less_than:200000 }, :if => :paid_gigs
before_save :check_lat_lng
before_save :check_website_url

View File

@ -145,9 +145,10 @@ module JamRuby
end
end
if music_session.is_recording?
errors.add(:music_session, ValidationMessages::CANT_JOIN_RECORDING_SESSION)
end
#removing this check to allow users to join recording sessions
# if music_session.is_recording?
# errors.add(:music_session, ValidationMessages::CANT_JOIN_RECORDING_SESSION)
# end
# same logic as Search.scope_schools_together_sessions
if !self.user.is_platform_instructor

View File

@ -31,9 +31,12 @@ module JamRuby
target_user = params[:user]
target_band = params[:band]
# TODO: SPEED UP QUERY. CURRENTLY TAKES FOR EVER.
if target_user or target_band
return { query: [], next_page: nil}
if Rails.application.config.targeted_feed_disabled
if target_user or target_band
return { query: [], next_page: nil}
end
end
#query = Feed.includes([:recording]).includes([:music_session]).limit(limit)

View File

@ -60,7 +60,7 @@ module JamRuby
end
def verify_download_count
if (self.download_count < 0 || self.download_count > MAX_JAM_TRACK_DOWNLOADS) && !@current_user.admin
if (self.download_count < 0 || self.download_count > MAX_JAM_TRACK_DOWNLOADS) && !self.user.admin
errors.add(:download_count, "must be less than or equal to #{MAX_JAM_TRACK_DOWNLOADS}")
end
end

View File

@ -33,7 +33,7 @@ module JamRuby
dependent: :destroy
validate :not_already_recording, :on => :create
validate :not_still_finalizing_previous, :on => :create
#validate :not_still_finalizing_previous, :on => :create
validate :not_playback_recording, :on => :create
validate :already_stopped_recording
validate :only_one_mix
@ -75,6 +75,10 @@ module JamRuby
has_stream_mix
end
def can_stop?(user)
# only allow the starting-user to create (ideally, perhaps, only the client that did it)
user == owner
end
# this should be a has-one relationship. until this, this is easiest way to get from recording > mix
def mix
self.mixes[0] if self.mixes.length > 0
@ -214,7 +218,7 @@ module JamRuby
def has_access?(user)
return false if user.nil?
users.exists?(user.id) || attached_with_lesson(user) #|| plays.where("player_id=?", user).count != 0
users.exists?(user.id) || attached_with_lesson(user) || (music_session && music_session.in_session?(user))
end
def attached_with_lesson(user)

View File

@ -75,7 +75,7 @@ module JamRuby
rel = case params[SEARCH_TEXT_TYPE_ID].to_s
when 'bands'
@search_type = :bands
Band.where(nil)
Band.where(nil).joins(:users)
when 'fans'
@search_type = :fans
User.fans.not_deleted
@ -83,8 +83,13 @@ module JamRuby
@search_type = :musicians
User.musicians.not_deleted
end
@results = rel.where("(name_tsv @@ to_tsquery('jamenglish', ?))", tsquery).limit(10)
if @search_type == :bands
@results = rel.where("(bands.name_tsv @@ to_tsquery('jamenglish', ?))", tsquery)
else
@results = rel.where("(users.name_tsv @@ to_tsquery('jamenglish', ?))", tsquery)
end
@results = @results.limit(40)
@results = Search.scope_schools_together(@results, user)
end

View File

@ -21,6 +21,7 @@ module JamRuby
JAM_REASON_JOIN = 'j'
JAM_REASON_IMPORT = 'i'
JAM_REASON_LOGIN = 'l'
JAM_REASON_PRESENT = 'p'
# MOD KEYS
MOD_GEAR = "gear"
@ -72,7 +73,7 @@ module JamRuby
after_save :update_teacher_pct
attr_accessible :first_name, :last_name, :email, :city, :password, :password_confirmation, :state, :country, :birth_date, :subscribe_email, :terms_of_service, :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection, :used_current_month, :used_month_play_time
attr_accessible :first_name, :last_name, :email, :city, :password, :password_confirmation, :state, :country, :birth_date, :subscribe_email, :terms_of_service, :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection, :used_current_month, :used_month_play_time, :facebook_click_id, :facebook_browser_id
# updating_password corresponds to a lost_password
attr_accessor :test_drive_packaging, :validate_instruments, :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json, :expecting_gift_card, :purchase_required, :user_type
@ -281,7 +282,7 @@ module JamRuby
validates :is_onboarder, :inclusion => {:in => [true, false, nil]}
#validates :mods, json: true
validates_numericality_of :last_jam_audio_latency, greater_than: MINIMUM_AUDIO_LATENCY, less_than: MAXIMUM_AUDIO_LATENCY, :allow_nil => true
validates :last_jam_updated_reason, :inclusion => {:in => [nil, JAM_REASON_REGISTRATION, JAM_REASON_NETWORK_TEST, JAM_REASON_FTUE, JAM_REASON_JOIN, JAM_REASON_IMPORT, JAM_REASON_LOGIN]}
validates :last_jam_updated_reason, :inclusion => {:in => [nil, JAM_REASON_REGISTRATION, JAM_REASON_NETWORK_TEST, JAM_REASON_FTUE, JAM_REASON_JOIN, JAM_REASON_IMPORT, JAM_REASON_LOGIN, JAM_REASON_PRESENT]}
# stored in cents
validates_numericality_of :paid_sessions_hourly_rate, greater_than: 0, less_than: 200000, :if => :paid_sessions
@ -494,6 +495,23 @@ module JamRuby
@updating_progression_field = true
if self[field_name].nil?
self[field_name] = time
# CAPI Hooks
begin
case field_name.to_s
when 'first_ran_client_at'
# StartTrial: When user opens the app (progression field updated usually via API)
CapiTransmitter.send_event('StartTrial', self, { value: '0.00', currency: 'USD', predicted_ltv: '0.00' })
when 'first_certified_gear_at'
# AddToCart: When user completes gear setup
CapiTransmitter.send_event('AddToCart', self)
end
rescue => e
# Fail silently but log, don't break progression update
@@log.error("CAPI error in update_progression_field: #{field_name} #{e.message}")
puts("CAPI error in update_progression_field: #{field_name} #{e.message}")
end
self.save
end
end
@ -1501,6 +1519,8 @@ module JamRuby
license_end = options[:license_end]
import_source = options[:import_source]
desired_plan_code = options[:desired_plan_code]
facebook_click_id = options[:facebook_click_id]
facebook_browser_id = options[:facebook_browser_id]
if desired_plan_code == ''
desired_plan_code = nil
@ -1567,11 +1587,17 @@ module JamRuby
user.origin_utm_source = origin["utm_source"]
user.origin_utm_medium = origin["utm_medium"]
user.origin_utm_campaign = origin["utm_campaign"]
user.origin_id = origin["utm_id"]
user.origin_term = origin["utm_term"]
user.origin_content = origin["utm_content"]
user.origin_referrer = origin["referrer"]
else
user.origin_utm_source = 'organic'
user.origin_utm_medium = 'organic'
user.origin_utm_campaign = nil
user.origin_id = nil
user.origin_term = nil
user.origin_content = nil
user.origin_referrer = nil
end
@ -1656,6 +1682,9 @@ module JamRuby
end
end
user.facebook_click_id = facebook_click_id
user.facebook_browser_id = facebook_browser_id
unless fb_signup.nil?
user.update_fb_authorization(fb_signup)
@ -1718,6 +1747,16 @@ module JamRuby
user.save
# CAPI: CompleteRegistration
# Fire only if we have attribution data (click_id) indicating they came from FB
if user.persisted? && user.facebook_click_id.present?
begin
CapiTransmitter.send_event('CompleteRegistration', user)
rescue => e
@@log.error("CAPI CompleteRegistration error: #{e.message}")
end
end
# now that the user is saved, let's
if invited_user && invited_user.autofriend && !invited_user.sender.nil?
# hookup this user with the sender

View File

@ -336,6 +336,33 @@ module JamRuby
end
end
def report_meta_capi(current_user, plan_code)
# CAPI Hook: Subscribe
begin
monthly_cost = case plan_code
when JamRuby::SubscriptionDefinitions::JAM_SILVER, JamRuby::SubscriptionDefinitions::JAM_SILVER_YEARLY
5.00
when JamRuby::SubscriptionDefinitions::JAM_GOLD, JamRuby::SubscriptionDefinitions::JAM_GOLD_YEARLY
10.00
when JamRuby::SubscriptionDefinitions::JAM_PLATINUM, JamRuby::SubscriptionDefinitions::JAM_PLATINUM_YEARLY
20.00
else
0.00
end
ltv = monthly_cost * 12
begin
puts "Sending CAPI Subscribe event #{current_user.email}, #{monthly_cost}, #{ltv}"
CapiTransmitter.send_event('Subscribe', current_user, { value: monthly_cost.to_s, currency: 'USD', predicted_ltv: ltv.to_s })
rescue => e
puts "Error sending CAPI Subscribe event #{current_user.email}, #{e.message}"
end
rescue => e
puts "Error sending CAPI Subscribe event #{current_user.email}, #{e.message}"
end
end
def get_highest_plan(subscription)
SubscriptionDefinitions.higher_plan(subscription.plan.plan_code, get_pending_plan_code(subscription))
end
@ -364,6 +391,8 @@ module JamRuby
end
current_user.reset_playtime
current_user.save(validate: false)
report_meta_capi(current_user, plan_code)
rescue => e
puts "Could not create subscription for user #{current_user.email}. #{e}"
return false, subscription, account
@ -704,7 +733,8 @@ module JamRuby
end
if !recurly_token.nil?
update_billing_info_from_token(current_user, account, recurly_token)
puts "#{current_user.id} skipping double-update of billing of #{recurly_token} due to 2024 Oct Recurly Bug"
# update_billing_info_from_token(current_user, account, recurly_token)
end
account
end

View File

@ -533,7 +533,11 @@ describe Recording do
@user.first_recording_at.should_not be_nil
end
describe "chance for everyone to keep or discard" do
#NOTE: change in recording flow. Now after stopping the recording we no longer ask
#user to save or discard the recording, instead the app saves the recording to user's
#computer and opens the file explorer to that folder.
#therefore following scenario is no longer valid; hence skipping it.
xdescribe "chance for everyone to keep or discard" do
before(:each) do
@user2 = FactoryGirl.create(:user)
@connection2 = FactoryGirl.create(:connection, :user => @user2, :music_session => @music_session)

View File

@ -82,6 +82,10 @@ def app_config
false
end
def targeted_feed_disabled
false
end
def audiomixer_path
# you can specify full path to audiomixer with AUDIOMIXER_PATH env variable...
# or we check for audiomixer path in the user's workspace

View File

@ -554,6 +554,8 @@ GEM
rabl (0.13.1)
activesupport (>= 2.3.14)
rack (1.6.13)
rack-cors (1.0.6)
rack (>= 1.6.0)
rack-oauth2 (1.12.0)
activesupport
attr_required
@ -873,6 +875,7 @@ DEPENDENCIES
puma
quiet_assets
rabl (= 0.13.1)
rack-cors (~> 1.0, >= 1.0.6)
rack-test
rails (= 4.2.8)
rails-assets-bluebird!

View File

@ -1,7 +1,34 @@
Jasmine Javascript Unit Tests
=============================
Open browser to localhost:3000/teaspoon
Test
##Custom URL Scheme handling
URLs starting as jamkazam:// are considered custom urls that can be used to open up / bring up the JK client program
and load a screen or call an internal function.
Let's say a user clicks or submits a from which in turns call a custom URL.
For example in the new react web interface, when a session is created using the form in https://www.jamkazam.com/sessions/new let's say it calls following custom URL
jamkazam://https//www.jamkazam.com/client#/createSession/custom~yes%7Cprivacy~2%7Cdescription~Testing%20session%20creation%20from%20beta%20website%7CinviteeIds~062deeba-b917-46e2-bfa3-e829405ca602
In the JK client this url is passed to the front end by the back end either by
1) onLoggedIn - This function is been called when the client is loaded (after user login). Used to handled the CustomUrl if the app is not already up and running
2) asyncJamClient 3012 event - If the app is up and running this event is fired with the CustomUrl
In either case the CustomUrl is stored in the localStorage and handled by the respective function being called.
Currently we have two customUrls
1) Session create by custom URL - call it using shell by
open "jamkazam://www.jamkazam.com/client#/createSession/custom~yes%7Cprivacy~2%7Cdescription~Testing%20session%20creation%20from%20beta%20website%7CinviteeIds~062deeba-b917-46e2-bfa3-e829405ca602"
2) Join to an existing session
open "jamkazam://www.jamkazam.com/client#/joinSession/custom~yes%7CsessionId~3190c211-f741-47d1-9171-05cf8df020d0"
Tets

View File

@ -27,8 +27,6 @@
"error" : 1
}
var logCache = [];
if ('undefined' === typeof(context.console)) {
context.console = {};
$.each(console_methods, function(index, value) {
@ -62,11 +60,6 @@
logAsString.push("unable to parse node: " + e.toString());
}
}
logCache.push([method].concat(logAsString));
if(logCache.length > 50) {
// keep the cache size 50 or lower
logCache.shift();
}
if (original.apply){
// Do this for normal browsers
@ -92,7 +85,6 @@
takeOverConsole();
context.JK.logger = context.console;
context.JK.logger.logCache = logCache;
})(window, jQuery);

File diff suppressed because it is too large Load Diff

View File

@ -45,22 +45,24 @@
var invalidProfiles = prettyPrintAudioProfiles(context.JK.getBadConfigMap());
var sessionSummary = summarizeSession(userDetail);
if(gon.global.video_available && gon.global.video_available!="none" ) {
var webcamName;
var webcam = null;
if (context.jamClient.FTUECurrentSelectedVideoDevice) {
webcam = context.jamClient.FTUECurrentSelectedVideoDevice()
}
// if(gon.global.video_available && gon.global.video_available!="none" ) {
// var webcamName;
// var webcam = null;
// //if (context.jamClient.FTUECurrentSelectedVideoDevice) {
// webcam = await context.jamClient.FTUECurrentSelectedVideoDevice()
// //}
if (webcam == null || typeof(webcam) == "undefined" || Object.keys(webcam).length == 0) {
webcamName = "None Configured"
} else {
webcamName = _.values(webcam)[0]
}
}
else {
webcamName = 'video unavailable'
}
// if (webcam == null || typeof(webcam) == "undefined" || Object.keys(webcam).length == 0) {
// webcamName = "None Configured"
// } else {
// webcamName = _.values(webcam)[0]
// }
// }
// else {
// webcamName = 'video unavailable'
// }
var webcamName = 'video available in session';
var $template = $(context._.template($('#template-account-main').html(), {
email: userDetail.email,

View File

@ -56,29 +56,31 @@
$root.find('a[data-purpose=reload-audio]').addClass('disabled')
$root.find('.rescanning-notice').show();
},
function(canceled) {
async function(canceled) {
$root.find('a[data-purpose=reload-audio]').removeClass('disabled')
$root.find('.rescanning-notice').hide();
if(!canceled) {
var result = context.jamClient.ReloadAudioSystem(false, true, true);
var result = await context.jamClient.ReloadAudioSystem(false, true, true);
}
populateAccountAudio();
});
}
function onUsbDeviceConnected() {
async function onUsbDeviceConnected() {
if(showingGearWizard) { return; } // gear wizard also handles these events; unpredictable if both are rebuilding port audio
if(!context.jamClient.IsFrontendVisible()) {return;} // don't handle USB events when minimized
var isFrontendVisible = await context.jamClient.IsFrontendVisible();
if(!isFrontendVisible) {return;} // don't handle USB events when minimized
logger.debug("USB device connected");
scheduleRescanSystem(5000);
}
function onUsbDeviceDisconnected() {
async function onUsbDeviceDisconnected() {
if(showingGearWizard) { return; } // gear wizard also handles these events; unpredictable if both are rebuilding port audio
if(!context.jamClient.IsFrontendVisible()) {return;} // don't handle USB events when minimized
var isFrontendVisible = await context.jamClient.IsFrontendVisible();
if(!isFrontendVisible) {return;} // don't handle USB events when minimized
logger.debug("USB device disconnected");
@ -100,8 +102,8 @@
}
}
function populateAccountAudio() {
var profiles = gearUtils.getProfiles();
async function populateAccountAudio() {
var profiles = await gearUtils.getProfiles();
context._.each(profiles, function(profile) {
profile.active_text = profile.current ? '(active)' : '';
@ -111,14 +113,17 @@
// then you will have 'FTUE' (incomplete) profiles. This is the only time
var cleansedProfiles = [];
context._.each(profiles, function(profile) {
//context._.each(profiles, async function(profile) {
for (const profile of profiles) {
if(profile.id.indexOf('FTUE') == 0) {
context.jamClient.TrackDeleteProfile(profile.id);
await context.jamClient.TrackDeleteProfile(profile.id);
}
else {
cleansedProfiles.push(profile)
}
});
}
//});
var template = context._.template($('#template-account-audio').html(), {is_admin: context.JK.currentUserAdmin, profiles: cleansedProfiles}, {variable: 'data'});
@ -134,19 +139,18 @@
function resetForm() {
}
function handleDeleteAudioProfile(audioProfileId) {
logger.debug("deleting audio profile: " + audioProfileId);
context.jamClient.TrackDeleteProfile(audioProfileId);
async function handleDeleteAudioProfile(audioProfileId) {
console.log("deleting audio profile: " + audioProfileId);
await context.jamClient.TrackDeleteProfile(audioProfileId, true);
// redraw after deletion of profile
populateAccountAudio();
await populateAccountAudio();
}
function handleLoopbackAudioProfile(audioProfileId) {
async function handleLoopbackAudioProfile(audioProfileId) {
if(audioProfileId != context.jamClient.FTUEGetMusicProfileName()) {
var result = context.jamClient.FTUELoadAudioConfiguration(audioProfileId);
if(audioProfileId != await context.jamClient.FTUEGetMusicProfileName()) {
var result = await context.jamClient.FTUELoadAudioConfiguration(audioProfileId);
if(!result) {
logger.error("unable to activate audio configuration: " + audioProfileId);
@ -154,14 +158,14 @@
}
else {
// redraw after activation of profile
populateAccountAudio();
await populateAccountAudio();
}
}
app.layout.showDialog('loopback-wizard');
}
function handleConfigureAudioProfile(audioProfileId) {
async function handleConfigureAudioProfile(audioProfileId) {
if(!gearUtils.canBeConfigured(audioProfileId)) {
@ -170,9 +174,9 @@
}
if(audioProfileId == gearUtils.GearUtil)
if(audioProfileId != context.jamClient.FTUEGetMusicProfileName()) {
if(audioProfileId != await context.jamClient.FTUEGetMusicProfileName()) {
logger.debug("activating " + audioProfileId);
var result = context.jamClient.FTUELoadAudioConfiguration(audioProfileId);
var result = await context.jamClient.FTUELoadAudioConfiguration(audioProfileId);
if(!result) {
logger.error("unable to activate audio configuration: " + audioProfileId);
@ -181,7 +185,7 @@
}
// FTUELoadAudioConfiguration eventually sets this, but apparently asynchronously
result = context.jamClient.SetLastUsedProfileName(audioProfileId);
result = await context.jamClient.SetLastUsedProfileName(audioProfileId);
if(!result) {
logger.error("unable to activate audio configuration after loading it: " + audioProfileId);
@ -190,22 +194,25 @@
}
// redraw after activation of profile
populateAccountAudio();
await populateAccountAudio();
}
app.layout.showDialog('configure-tracks')
.one(EVENTS.DIALOG_CLOSED, populateAccountAudio)
.one(EVENTS.DIALOG_CLOSED, async function(){
await populateAccountAudio()
})
}
function handleActivateAudioProfile(audioProfileId) {
async function handleActivateAudioProfile(audioProfileId) {
logger.debug("activating audio profile: " + audioProfileId);
if(audioProfileId == context.jamClient.LastUsedProfileName()) {
if(audioProfileId == await context.jamClient.LastUsedProfileName()) {
context.JK.Banner.showAlert("This profile is already active.");
return;
}
var result = context.jamClient.SetLastUsedProfileName(audioProfileId);
var result = await context.jamClient.SetLastUsedProfileName(audioProfileId);
if(!result) {
logger.error("unable to activate audio configuration: " + audioProfileId);
@ -213,48 +220,52 @@
}
// redraw after activation of profile
populateAccountAudio();
await populateAccountAudio();
}
function handleStartAudioQualification() {
async function handleStartAudioQualification() {
app.afterFtue = function() {
app.afterFtue = async function() {
showingGearWizard = false;
if(populateAccountAudio().length == 1) {
if(await populateAccountAudio().length == 1) {
app.layout.showDialog('join-test-session');
}
};
app.cancelFtue = function() { showingGearWizard = false; populateAccountAudio() };
app.cancelFtue = async function() { showingGearWizard = false; await populateAccountAudio() };
showingGearWizard = true;
app.layout.startNewFtue()
}
function reloadAudio() {
async function reloadAudio() {
// false = don't start audio, true = reload last audio configuration, false = don't re-init tracks
context.jamClient.ReloadAudioSystem(false, true, false);
await context.jamClient.ReloadAudioSystem(false, true, false);
populateAccountAudio();
await populateAccountAudio();
}
function registerFtueSuccess() {
$('div[layout-id=ftue]').on("ftue_success", ftueSuccessHandler);
$('div[layout-id=ftue]').on("ftue_success", async function(){
await ftueSuccessHandler()
});
}
function unregisterFtueSuccess() {
$('div[layout-id=ftue]').off("ftue_success", ftueSuccessHandler);
$('div[layout-id=ftue]').off("ftue_success", async function(){
await ftueSuccessHandler();
});
}
function ftueSuccessHandler() {
populateAccountAudio();
async function ftueSuccessHandler() {
await populateAccountAudio();
}
// events for main screen
function events() {
// wire up main panel clicks
$root = $('#account-audio-content-scroller');
$root.on('click', 'a[data-purpose=delete-audio-profile]', function (evt) {
$root.on('click', 'a[data-purpose=delete-audio-profile]', async function (evt) {
evt.stopPropagation();
handleDeleteAudioProfile($(this).attr('data-id'));
await handleDeleteAudioProfile($(this).attr('data-id'));
return false;
});
@ -286,13 +297,13 @@
return false;
});
$root.on('click', 'a[data-purpose=configure-audio-profile]', function (evt) {
$root.on('click', 'a[data-purpose=configure-audio-profile]', async function (evt) {
evt.stopPropagation();
var $btn = $(this);
var status = $btn.closest('tr').attr('data-status');
if(status == "good") {
cancelRescan();
handleConfigureAudioProfile($btn.attr('data-id'));
await handleConfigureAudioProfile($btn.attr('data-id'));
}
else {
context.JK.Banner.showAlert("Unable to configure this profile. Please verify that the devices associated are connected.");
@ -301,10 +312,10 @@
});
$root.on('click', 'a[data-purpose=add-profile]', function (evt) {
$root.on('click', 'a[data-purpose=add-profile]', async function (evt) {
evt.stopPropagation();
cancelRescan();
handleStartAudioQualification();
await handleStartAudioQualification();
return false;
});

View File

@ -57,49 +57,101 @@ context.JK.AccountJamTracks = class AccountJamTracks
@createSession(jamRow.data(), false, jamRow.data('jamTrack'))
return false;
createSession:(sessionData, solo, jamTrack) =>
tracks = context.JK.TrackHelpers.getUserTracks(context.jamClient)
# createSession:(sessionData, solo, jamTrack) =>
# tracks = context.JK.TrackHelpers.getUserTracks(context.jamClient)
if (context.JK.guardAgainstBrowser(@app))
data = {}
data.client_id = @app.clientId
#data.description = $('#description').val()
data.description = "Jam Track Session"
data.as_musician = true
data.legal_terms = true
data.intellectual_property = true
data.approval_required = false
data.musician_access = !solo
data.fan_access = false
data.fan_chat = false
data.genre = $.map(sessionData.jamTrack.genres, (genre) -> genre.id)
data.genres = $.map(sessionData.jamTrack.genres, (genre)-> genre.id)
# data.genres = context.JK.GenreSelectorHelper.getSelectedGenres('#create-session-genre')
# data.musician_access = if $('#musician-access option:selected').val() == 'true' then true else false
# data.approval_required = if $('input[name=\'musician-access-option\']:checked').val() == 'true' then true else false
# data.fan_access = if $('#fan-access option:selected').val() == 'true' then true else false
# data.fan_chat = if $('input[name=\'fan-chat-option\']:checked').val() == 'true' then true else false
# if $('#band-list option:selected').val() != ''
# data.band = $('#band-list option:selected').val()
data.audio_latency = context.jamClient.FTUEGetExpectedLatency().latency
data.tracks = tracks
# if (context.JK.guardAgainstBrowser(@app))
# data = {}
# data.client_id = @app.clientId
# #data.description = $('#description').val()
# data.description = "Jam Track Session"
# data.as_musician = true
# data.legal_terms = true
# data.intellectual_property = true
# data.approval_required = false
# data.musician_access = !solo
# data.fan_access = false
# data.fan_chat = false
# data.genre = $.map(sessionData.jamTrack.genres, (genre) -> genre.id)
# data.genres = $.map(sessionData.jamTrack.genres, (genre)-> genre.id)
# # data.genres = context.JK.GenreSelectorHelper.getSelectedGenres('#create-session-genre')
# # data.musician_access = if $('#musician-access option:selected').val() == 'true' then true else false
# # data.approval_required = if $('input[name=\'musician-access-option\']:checked').val() == 'true' then true else false
# # data.fan_access = if $('#fan-access option:selected').val() == 'true' then true else false
# # data.fan_chat = if $('input[name=\'fan-chat-option\']:checked').val() == 'true' then true else false
# # if $('#band-list option:selected').val() != ''
# # data.band = $('#band-list option:selected').val()
# data.audio_latency = context.jamClient.FTUEGetExpectedLatency().latency
# data.tracks = tracks
rest.legacyCreateSession(data).done((response) =>
newSessionId = response.id
@sessionUtils.setAutoOpenJamTrack(jamTrack) # so that the session screen will pick this up
context.location = '/client#/session/' + newSessionId
# Re-loading the session settings will cause the form to reset with the right stuff in it.
# This is an extra xhr call, but it keeps things to a single codepath
#loadSessionSettings()
context.JK.GA.trackSessionCount data.musician_access, data.fan_access, 0
context.JK.GA.trackSessionMusicians context.JK.GA.SessionCreationTypes.create
).fail (jqXHR) =>
handled = false
if jqXHR.status = 422
response = JSON.parse(jqXHR.responseText)
if response['errors'] and response['errors']['tracks'] and response['errors']['tracks'][0] == 'Please select at least one track'
@app.notifyAlert 'No Inputs Configured', $('<span>You will need to reconfigure your audio device.</span>')
handled = true
if !handled
@app.notifyServerError jqXHR, 'Unable to Create Session'
# rest.legacyCreateSession(data).done((response) =>
# newSessionId = response.id
# @sessionUtils.setAutoOpenJamTrack(jamTrack) # so that the session screen will pick this up
# context.location = '/client#/session/' + newSessionId
# # Re-loading the session settings will cause the form to reset with the right stuff in it.
# # This is an extra xhr call, but it keeps things to a single codepath
# #loadSessionSettings()
# context.JK.GA.trackSessionCount data.musician_access, data.fan_access, 0
# context.JK.GA.trackSessionMusicians context.JK.GA.SessionCreationTypes.create
# ).fail (jqXHR) =>
# handled = false
# if jqXHR.status = 422
# response = JSON.parse(jqXHR.responseText)
# if response['errors'] and response['errors']['tracks'] and response['errors']['tracks'][0] == 'Please select at least one track'
# @app.notifyAlert 'No Inputs Configured', $('<span>You will need to reconfigure your audio device.</span>')
# handled = true
# if !handled
# @app.notifyServerError jqXHR, 'Unable to Create Session'
createSession: `async function(sessionData, solo, jamTrack){
const tracks = await context.JK.TrackHelpers.getUserTracks(context.jamClient);
if (context.JK.guardAgainstBrowser(this.app)) {
const data = {};
data.client_id = this.app.clientId;
//data.description = $('#description').val()
data.description = "Jam Track Session";
data.as_musician = true;
data.legal_terms = true;
data.intellectual_property = true;
data.approval_required = false;
data.musician_access = !solo;
data.fan_access = false;
data.fan_chat = false;
data.genre = $.map(sessionData.jamTrack.genres, genre => genre.id);
data.genres = $.map(sessionData.jamTrack.genres, genre => genre.id);
// data.genres = context.JK.GenreSelectorHelper.getSelectedGenres('#create-session-genre')
// data.musician_access = if $('#musician-access option:selected').val() == 'true' then true else false
// data.approval_required = if $('input[name=\'musician-access-option\']:checked').val() == 'true' then true else false
// data.fan_access = if $('#fan-access option:selected').val() == 'true' then true else false
// data.fan_chat = if $('input[name=\'fan-chat-option\']:checked').val() == 'true' then true else false
// if $('#band-list option:selected').val() != ''
// data.band = $('#band-list option:selected').val()
let expectedLatency = await context.jamClient.FTUEGetExpectedLatency()
data.audio_latency = expectedLatency.latency;
data.tracks = tracks;
return rest.legacyCreateSession(data).done(response => {
const newSessionId = response.id;
this.sessionUtils.setAutoOpenJamTrack(jamTrack); // so that the session screen will pick this up
context.location = '/client#/session/' + newSessionId;
// Re-loading the session settings will cause the form to reset with the right stuff in it.
// This is an extra xhr call, but it keeps things to a single codepath
//loadSessionSettings()
context.JK.GA.trackSessionCount(data.musician_access, data.fan_access, 0);
return context.JK.GA.trackSessionMusicians(context.JK.GA.SessionCreationTypes.create);
}).fail(jqXHR => {
let handled = false;
if (jqXHR.status = 422) {
const response = JSON.parse(jqXHR.responseText);
if (response['errors'] && response['errors']['tracks'] && (response['errors']['tracks'][0] === 'Please select at least one track')) {
this.app.notifyAlert('No Inputs Configured', $('<span>You will need to reconfigure your audio device.</span>'));
handled = true;
}
}
if (!handled) {
return this.app.notifyServerError(jqXHR, 'Unable to Create Session');
}
});
}
}`

View File

@ -74,22 +74,22 @@
track2AudioInputChannels = _loadList(ASSIGNMENT.TRACK2, true, false);
}
function _loadList(assignment, input, chat) {
async function _loadList(assignment, input, chat) {
var list = [];
// get data needed for listboxes
var channels = context.jamClient.TrackGetChannels();
var channels = await context.jamClient.TrackGetChannels();
var musicDevices = context.jamClient.TrackGetMusicDeviceNames(input);
var musicDevices = await context.jamClient.TrackGetMusicDeviceNames(input);
// SEE loadList function in TrackAssignGui.cpp of client code
$.each(channels, function(index, val) {
$.each(channels, async function(index, val) {
if (input !== val.input) {
return;
}
var currAssignment = context.jamClient.TrackGetAssignment(val.id, val.input);
var currAssignment = await context.jamClient.TrackGetAssignment(val.id, val.input);
if (assignment !== currAssignment) {
return;
}
@ -97,9 +97,9 @@
logger.debug("channel id=" + val.id + ", channel input=" + val.input + ", channel assignment=" + currAssignment +
", channel name=" + val.name + ", channel type=" + val.device_type + ", chat=" + val.chat);
var os = context.jamClient.GetOSAsString();
var os = await context.jamClient.GetOSAsString();
if (os === context.JK.OS.WIN32) {
if (chat && ($.inArray(val.device_id, musicDevices) > -1 || context.jamClient.TrackIsMusicDeviceType(val.device_type))) {
if (chat && ($.inArray(val.device_id, musicDevices) > -1 || await context.jamClient.TrackIsMusicDeviceType(val.device_type))) {
return;
}
}
@ -137,13 +137,13 @@
app.layout.closeDialog('add-track');
}
function saveTrack() {
async function saveTrack() {
// TRACK 2 INPUTS
var trackId = null;
$("#add-track2-input > option").each(function() {
$("#add-track2-input > option").each(async function() {
logger.debug("Saving track 2 input = " + this.value);
trackId = this.value;
context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK2);
await context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK2);
});
// TRACK 2 INSTRUMENT
@ -151,13 +151,13 @@
var instrumentText = $('#add-track2-instrument > option:selected').text().toLowerCase();
logger.debug("Saving track 2 instrument = " + instrumentVal);
context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK2, instrumentVal);
await context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK2, instrumentVal);
// UPDATE SERVER
logger.debug("Adding track with instrument " + instrumentText);
var data = {};
context.jamClient.TrackSaveAssignments();
await context.jamClient.TrackSaveAssignments();
/**
setTimeout(function() {

View File

@ -74,4 +74,4 @@
//= require_directory ./wizard
//= require_directory ./wizard/gear
//= require_directory ./wizard/loopback
//= require everywhere/everywhere
//= require everywhere/everywhere

View File

@ -0,0 +1,716 @@
(function (context, $) {
"use strict";
context.JK = context.JK || {};
class Deferred {
constructor(request_id) {
var self = this;
this.request_id = request_id;
this.promise = new Promise(function (resolve, reject) {
self.reject = reject;
self.resolve = resolve;
});
}
}
context.JK.AsyncJamClient = function (app) {
const self = this;
const logger = context.JK.logger;
let deferredQueue = [];
let jkfrontendchannel = null;
let enumAppCounter = 1000;
let request_id = 1;
const JKFrontendMethods = Object.freeze({
UnknownJKAppMessage: enumAppCounter++,
AbortRecording: enumAppCounter++,
addUserBackingTracksToJamkazamAsset: enumAppCounter++,
applySubscriptionPolicy: enumAppCounter++,
BringVideoWindowToFront: enumAppCounter++,
browseForUserBackingTracksCandidate: enumAppCounter++,
cancelVideoUpload: enumAppCounter++,
clientID: enumAppCounter++,
ClientJoinedSession: enumAppCounter++,
ClientLeftSession: enumAppCounter++,
ClientUpdateStartDownload: enumAppCounter++,
ClientUpdateStartUpdate: enumAppCounter++,
ClientUpdateVersion: enumAppCounter++,
ClosePreviewRecording: enumAppCounter++,
CloseRecording: enumAppCounter++,
deleteVideo: enumAppCounter++,
DownloadFileStatus: enumAppCounter++,
endPairing: enumAppCounter++,
FTUEAudioResync: enumAppCounter++,
FTUECancel: enumAppCounter++,
FTUEChatFrameSize: enumAppCounter++,
FTUEClearChannelAssignments: enumAppCounter++,
FTUEClearChatInput: enumAppCounter++,
FTUECreateUpdatePlayBackProfile: enumAppCounter++,
FTUECurrentSelectedVideoDevice: enumAppCounter++,
FTUEGetAllAudioConfigurations: enumAppCounter++,
FTUEGetAllConfigurationList: enumAppCounter++,
FTUEGetAudioConfigurationsMissingDevice: enumAppCounter++,
FTUEGetAudioDevices: enumAppCounter++,
FTUEGetAutoSelectVideoLayout: enumAppCounter++,
FTUEGetAvailableEncodeVideoResolutions: enumAppCounter++,
FTUEGetAvailableVideoLayoutGroupStyles: enumAppCounter++,
FTUEGetBadConfigurationMissingDev: enumAppCounter++,
FTUEGetCaptureResolution: enumAppCounter++,
FTUEGetChannels: enumAppCounter++,
FTUEGetChatInputs: enumAppCounter++,
FTUEGetChatInputVolume: enumAppCounter++,
FTUEGetChatLatency: enumAppCounter++,
FTUEGetConfigurationDevice: enumAppCounter++,
FTUEGetConfigurationDevs: enumAppCounter++,
FTUEGetCurrentCaptureResolution: enumAppCounter++,
FTUEGetCurrentVideoCaptureDeviceCapability: enumAppCounter++,
FTUEGetDefaultAudioConfigurations: enumAppCounter++,
FTUEGetDevices: enumAppCounter++,
FTUEGetExpectedLatency: enumAppCounter++,
FTUEGetFrameSize: enumAppCounter++,
FTUEGetGoodAudioConfigurations: enumAppCounter++,
FTUEGetGoodConfigurationList: enumAppCounter++,
FTUEgetInputDeviceSampleRate: enumAppCounter++,
FTUEGetInputLatency: enumAppCounter++,
FTUEGetInputMusicDevice: enumAppCounter++,
FTUEGetInputVolume: enumAppCounter++,
FTUEGetIoPerfData: enumAppCounter++,
FTUEGetMapUserCntPreferredVideoLayoutGroupStyle: enumAppCounter++,
FTUEGetMusicInputs: enumAppCounter++,
FTUEGetMusicOutputs: enumAppCounter++,
FTUEGetMusicProfileName: enumAppCounter++,
FTUEgetOutputDeviceSampleRate: enumAppCounter++,
FTUEGetOutputLatency: enumAppCounter++,
FTUEGetOutputMusicDevice: enumAppCounter++,
FTUEGetOutputVolume: enumAppCounter++,
FTUEGetPreferredChatSampleRate: enumAppCounter++,
FTUEGetPreferredMixerSampleRate: enumAppCounter++,
FTUEGetPreferredOutputSampleRate: enumAppCounter++,
FTUEGetSendFrameRates: enumAppCounter++,
FTUEGetStatus: enumAppCounter++,
FTUEGetUserCountPreferredVideoLayoutGroupStyle: enumAppCounter++,
FTUEGetVideoCaptureDeviceCapabilities: enumAppCounter++,
FTUEGetVideoCaptureDeviceNames: enumAppCounter++,
FTUEGetVideoShareEnable: enumAppCounter++,
FTUEGetVolumeRanges: enumAppCounter++,
FTUEHasControlPanel: enumAppCounter++,
FTUEInit: enumAppCounter++,
FTUEIsMusicDeviceWDM: enumAppCounter++,
FTUELoadAudioConfiguration: enumAppCounter++,
FTUEOpenControlPanel: enumAppCounter++,
FTUEPageEnter: enumAppCounter++,
FTUEPageLeave: enumAppCounter++,
FTUERefreshDevices: enumAppCounter++,
FTUERegisterLatencyCallback: enumAppCounter++,
FTUERegisterVUCallbacks: enumAppCounter++,
FTUESave: enumAppCounter++,
FTUESelectVideoCaptureDevice: enumAppCounter++,
FTUESetAutoSelectVideoLayout: enumAppCounter++,
FTUESetCaptureResolution: enumAppCounter++,
FTUESetChatInput: enumAppCounter++,
FTUESetChatInputVolume: enumAppCounter++,
FTUESetChatLatency: enumAppCounter++,
FTUESetFrameSize: enumAppCounter++,
FTUESetInputLatency: enumAppCounter++,
FTUESetInputMusicDevice: enumAppCounter++,
FTUESetInputVolume: enumAppCounter++,
FTUESetLatencySamples: enumAppCounter++,
FTUESetMusicDevice: enumAppCounter++,
FTUESetMusicInput: enumAppCounter++,
FTUESetMusicInput2: enumAppCounter++,
FTUESetMusicOutput: enumAppCounter++,
FTUESetMusicProfileName: enumAppCounter++,
FTUESetOutputLatency: enumAppCounter++,
FTUESetOutputMusicDevice: enumAppCounter++,
FTUESetOutputVolume: enumAppCounter++,
FTUESetPreferredChatSampleRate: enumAppCounter++,
FTUESetPreferredMixerSampleRate: enumAppCounter++,
FTUESetPreferredOutputSampleRate: enumAppCounter++,
FTUESetPreferredVideoLayoutGroupStyle: enumAppCounter++,
FTUESetSendFrameRates: enumAppCounter++,
FTUESetStatus: enumAppCounter++,
FTUESetUserCountPreferredVideoLayoutGroupStyle: enumAppCounter++,
FTUESetVideoEncodeResolution: enumAppCounter++,
FTUESetVideoShareEnable: enumAppCounter++,
FTUEStartIoPerfTest: enumAppCounter++,
FTUEStartLatency: enumAppCounter++,
FTUEUnsetMusicInput2: enumAppCounter++,
get48vAndLineInstState: enumAppCounter++,
getABLoopState: enumAppCounter++,
getAllClientsStateMap: enumAppCounter++,
getAllClientsStateStr: enumAppCounter++,
GetASIODevices: enumAppCounter++,
GetAutoStart: enumAppCounter++,
getAvailableMetronomeClickNames: enumAppCounter++,
getBackingTrackList: enumAppCounter++,
getClientParentChildRole: enumAppCounter++,
getConnectionDetail: enumAppCounter++,
GetCurrentVideoFrameRate: enumAppCounter++,
GetCurrentVideoResolution: enumAppCounter++,
GetDetailedOS: enumAppCounter++,
GetFTUE: enumAppCounter++,
GetJamTrackSettings: enumAppCounter++,
GetJamTrackTimeline: enumAppCounter++,
getJBAutoPair: enumAppCounter++,
getJbNetworkState: enumAppCounter++,
getJbPortBindState: enumAppCounter++,
getJbPreampState: enumAppCounter++,
getJbStaticPortFlag: enumAppCounter++,
getJbStaticPortValue: enumAppCounter++,
getJbTrackState: enumAppCounter++,
getJbUsbState: enumAppCounter++,
GetLastLatencyTestTimes: enumAppCounter++,
getLatencyServerState: enumAppCounter++,
getLocalClients: enumAppCounter++,
GetLocalRecordingState: enumAppCounter++,
getLogLevel: enumAppCounter++,
getMetronomeCricketTestState: enumAppCounter++,
GetMixerIDs: enumAppCounter++,
GetMixerMode: enumAppCounter++,
GetMixerVolume: enumAppCounter++,
getMyChildren: enumAppCounter++,
getMyNetworkState: enumAppCounter++,
getMyParentState: enumAppCounter++,
GetNetworkTestScore: enumAppCounter++,
getOpenVideoSources: enumAppCounter++,
getOperatingMode: enumAppCounter++,
GetOS: enumAppCounter++,
GetOSAsString: enumAppCounter++,
getParentClientId: enumAppCounter++,
getPeerState: enumAppCounter++,
GetRecordingManagerState: enumAppCounter++,
GetSampleRate: enumAppCounter++,
GetScoreWorkTimingInterval: enumAppCounter++,
getSessionSetCompressorState: enumAppCounter++,
GetStaticPort: enumAppCounter++,
GetUseStaticPort: enumAppCounter++,
GetVideoNetworkTestScore: enumAppCounter++,
hasBonjour: enumAppCounter++,
hasVstAssignment: enumAppCounter++,
hasVstHost: enumAppCounter++,
hasWebrtc: enumAppCounter++,
InitiateScoringSession: enumAppCounter++,
InvalidateJamTrack: enumAppCounter++,
IsAppInWritableVolume: enumAppCounter++,
IsAudioStarted: enumAppCounter++,
IsFrontendVisible: enumAppCounter++,
isJamBlaster: enumAppCounter++,
isLatencyTestBlocked: enumAppCounter++,
IsMyNetworkWireless: enumAppCounter++,
IsNativeClient: enumAppCounter++,
IsSessionLiveBroadCastRunning: enumAppCounter++,
isSessionTrackPaused: enumAppCounter++,
isSessionTrackPlaying: enumAppCounter++,
isSessVideoRecording: enumAppCounter++,
isSessVideoShared: enumAppCounter++,
isSessYouTubeVideoBroadcasting: enumAppCounter++,
isVideoRecordingAllowed: enumAppCounter++,
isVideoWindowOpen: enumAppCounter++,
IsVstLoaded: enumAppCounter++,
isWebCamOpen: enumAppCounter++,
jamBlasterSerialNo: enumAppCounter++,
JamTrackDownload: enumAppCounter++,
JamTrackGetImage: enumAppCounter++,
JamTrackGetTrackDetail: enumAppCounter++,
JamTrackGetTracks: enumAppCounter++,
JamTrackIsPlayable: enumAppCounter++,
JamTrackIsPlaying: enumAppCounter++,
JamTrackKeysRequest: enumAppCounter++,
JamTrackLoadJmep: enumAppCounter++,
JamTrackPlay: enumAppCounter++,
JamTrackStopPlay: enumAppCounter++,
JoinSession: enumAppCounter++,
LastUsedProfileName: enumAppCounter++,
LeaveSession: enumAppCounter++,
LeaveSessionAndMinimize: enumAppCounter++,
log: enumAppCounter++,
NetworkTest: enumAppCounter++,
NetworkTestResult: enumAppCounter++,
OnDownloadAvailable: enumAppCounter++,
OnLoggedIn: enumAppCounter++,
OnLoggedInUserName: enumAppCounter++,
OnLoggedOut: enumAppCounter++,
OnTrySyncCommand: enumAppCounter++,
openBackingTrackFile: enumAppCounter++,
OpenBackingTracksDirectory: enumAppCounter++,
OpenRecording: enumAppCounter++,
OpenSystemBrowser: enumAppCounter++,
openVideo: enumAppCounter++,
P2PMessageReceived: enumAppCounter++,
ParticipantJoined: enumAppCounter++,
ParticipantLeft: enumAppCounter++,
pauseVideoUpload: enumAppCounter++,
PerformQuit: enumAppCounter++,
PostTaskBarMessage: enumAppCounter++,
PreviewRecording: enumAppCounter++,
rebootJamBlaster: enumAppCounter++,
RegisterGenericCallBack: enumAppCounter++,
registerMasterClippingCallback: enumAppCounter++,
RegisterMixerInterfaceModeChangeCallback: enumAppCounter++,
RegisterMuteChangeCallBack: enumAppCounter++,
RegisterQuitCallback: enumAppCounter++,
RegisterRecordingCallbacks: enumAppCounter++,
RegisterRecordingManagerCallbacks: enumAppCounter++,
RegisterSessionJoinLeaveRequestCallBack: enumAppCounter++,
RegisterVolChangeCallBack: enumAppCounter++,
ReloadAudioSystem: enumAppCounter++,
removeBackingTrackFiles: enumAppCounter++,
ResetPageCounters: enumAppCounter++,
RestartApplication: enumAppCounter++,
restartParentClient: enumAppCounter++,
resumeVideoUpload: enumAppCounter++,
SaveSettings: enumAppCounter++,
SaveToClipboard: enumAppCounter++,
SendP2PMessage: enumAppCounter++,
SessGetInsetPosition: enumAppCounter++,
SessGetListOfPeersSharingVideo: enumAppCounter++,
SessGetPeersVideoPosition: enumAppCounter++,
SessGetVideoDisplayLayoutGroup: enumAppCounter++,
SessGetVideoReceiveEnable: enumAppCounter++,
SessGetVideoRecordings: enumAppCounter++,
SessionAddPlayTrack: enumAppCounter++,
SessionAddTrack: enumAppCounter++,
SessionAudioResync: enumAppCounter++,
SessionCloseBackingTrackFile: enumAppCounter++,
SessionCloseMetronome: enumAppCounter++,
SessionCurrentPlaybackMode: enumAppCounter++,
SessionCurrrentJamTrackPlayPosMs: enumAppCounter++,
SessionCurrrentPlayPosMs: enumAppCounter++,
SessionFirstGet: enumAppCounter++,
SessionFirstSet: enumAppCounter++,
SessionGetAllControlState: enumAppCounter++,
SessionGetControlState: enumAppCounter++,
SessionGetDeviceLatency: enumAppCounter++,
SessionGetIDs: enumAppCounter++,
SessionGetJamTracksPlayDurationMs: enumAppCounter++,
SessionGetMacHash: enumAppCounter++,
SessionGetMasterLocalMix: enumAppCounter++,
SessionGetTracksPlayDurationMs: enumAppCounter++,
SessionJamTrackSeekMs: enumAppCounter++,
SessionLiveBroadcastStart: enumAppCounter++,
SessionLiveBroadcastStop: enumAppCounter++,
SessionOpenBackingTrackFile: enumAppCounter++,
SessionOpenMetronome: enumAppCounter++,
SessionPageEnter: enumAppCounter++,
SessionPageLeave: enumAppCounter++,
SessionPausePlay: enumAppCounter++,
SessionRegisterCallback: enumAppCounter++,
SessionRemoveAllPlayTracks: enumAppCounter++,
SessionRemovePlayTrack: enumAppCounter++,
SessionRemoveTrack: enumAppCounter++,
SessionRequestUserControlUpdate: enumAppCounter++,
SessionSetAlertCallback: enumAppCounter++,
SessionSetAlertPeriod: enumAppCounter++,
SessionSetConnectionStatusRefreshRate: enumAppCounter++,
SessionSetControlState: enumAppCounter++,
SessionSetMasterLocalMix: enumAppCounter++,
SessionSetMetronome: enumAppCounter++,
SessionSetRecordingFilename: enumAppCounter++,
SessionSetRecordingFolder: enumAppCounter++,
SessionSetTrackVolumeData: enumAppCounter++,
SessionSetUserData: enumAppCounter++,
SessionSetUserName: enumAppCounter++,
SessionShowMetronomeGui: enumAppCounter++,
SessionStartPlay: enumAppCounter++,
SessionStopPlay: enumAppCounter++,
SessionTrackSeekMs: enumAppCounter++,
SessionTracksSeek: enumAppCounter++,
SessPlayVideoRecording: enumAppCounter++,
SessRotatePeerVideoPositions: enumAppCounter++,
SessSelectVideoDisplayLayoutGroup: enumAppCounter++,
SessSetInsetPosition: enumAppCounter++,
SessSetInsetSize: enumAppCounter++,
SessSetPeersVideoPosition: enumAppCounter++,
SessSetVideoReceiveEnable: enumAppCounter++,
SessStartVideoRecordAndReturnFileName: enumAppCounter++,
SessStartVideoSharing: enumAppCounter++,
SessStartWebcamVideoRecordAndReturnFileName: enumAppCounter++,
SessStartYouTubeVideoBroadcast: enumAppCounter++,
SessStopVideoRecord: enumAppCounter++,
SessStopVideoSharing: enumAppCounter++,
SessStopYouTubeVideoBroadcast: enumAppCounter++,
SessSubscribePeerVideo: enumAppCounter++,
SessUnsubscribePeerVideo: enumAppCounter++,
set48vAndLineInstState: enumAppCounter++,
setABLoopState: enumAppCounter++,
SetAutoStart: enumAppCounter++,
setBackingTrackOpenCallback: enumAppCounter++,
SetFakeRecordingImpl: enumAppCounter++,
SetFTUE: enumAppCounter++,
setJBAutoPair: enumAppCounter++,
setJBName: enumAppCounter++,
setJbNetworkState: enumAppCounter++,
setJbPortBindState: enumAppCounter++,
setJbPreampState: enumAppCounter++,
setJbStaticPortFlag: enumAppCounter++,
setJbStaticPortValue: enumAppCounter++,
setJbTrackState: enumAppCounter++,
setJbUsbState: enumAppCounter++,
setJmepMetronomeVolume: enumAppCounter++,
SetLastUsedProfileName: enumAppCounter++,
SetLatencyTestBlocked: enumAppCounter++,
setMetronomeCricketTestState: enumAppCounter++,
setMetronomeOpenCallback: enumAppCounter++,
SetMixerMode: enumAppCounter++,
SetNetworkTestScore: enumAppCounter++,
SetRecordingFilename: enumAppCounter++,
SetRecordingFolder: enumAppCounter++,
SetScoreWorkTimingInterval: enumAppCounter++,
setSessionMixerCategoryPlayoutState: enumAppCounter++,
setSessionSetCompressorState: enumAppCounter++,
SetStaticPort: enumAppCounter++,
SetUseStaticPort: enumAppCounter++,
SetVideoNetworkTestScore: enumAppCounter++,
SetVURefreshRate: enumAppCounter++,
ShowSelectBackingTrackDialog: enumAppCounter++,
ShowSelectVSTScanDialog: enumAppCounter++,
ShutdownApplication: enumAppCounter++,
StartLiveStreaming: enumAppCounter++,
startPairing: enumAppCounter++,
StartRecording: enumAppCounter++,
StopAudio: enumAppCounter++,
StopLiveStreaming: enumAppCounter++,
StopNetworkTest: enumAppCounter++,
StopRecording: enumAppCounter++,
TestLatency: enumAppCounter++,
TestNetworkPktBwRate: enumAppCounter++,
testVideoRender: enumAppCounter++,
TrackDeleteProfile: enumAppCounter++,
TrackGetAssignment: enumAppCounter++,
TrackGetChannels: enumAppCounter++,
TrackGetChatEnable: enumAppCounter++,
TrackGetChatUsesMusic: enumAppCounter++,
TrackGetCount: enumAppCounter++,
TrackGetDevices: enumAppCounter++,
TrackGetInstrument: enumAppCounter++,
TrackGetMusicDeviceID: enumAppCounter++,
TrackGetMusicDeviceNames: enumAppCounter++,
TrackHasControlPanel: enumAppCounter++,
TrackIsMusicDeviceType: enumAppCounter++,
TrackLoadAssignments: enumAppCounter++,
TrackLoadAudioProfile: enumAppCounter++,
TrackOpenControlPanel: enumAppCounter++,
TrackRefreshDevices: enumAppCounter++,
TrackSaveAssignments: enumAppCounter++,
TrackSetAssignment: enumAppCounter++,
TrackSetChatEnable: enumAppCounter++,
TrackSetChatInput: enumAppCounter++,
TrackSetChatUsesMusic: enumAppCounter++,
TrackSetCount: enumAppCounter++,
TrackSetInstrument: enumAppCounter++,
TrackSetMusicDevice: enumAppCounter++,
UpdateMixer: enumAppCounter++,
UpdateSessionInfo: enumAppCounter++,
uploadVideo: enumAppCounter++,
UserAttention: enumAppCounter++,
VideoDecision: enumAppCounter++,
VSTAddSearchPath: enumAppCounter++,
VSTClearAll: enumAppCounter++,
VSTListSearchPaths: enumAppCounter++,
VSTListTrackAssignments: enumAppCounter++,
VSTListVsts: enumAppCounter++,
VSTLoad: enumAppCounter++,
VSTRemoveSearchPath: enumAppCounter++,
VSTScan: enumAppCounter++,
VSTSetTrackAssignment: enumAppCounter++,
VSTShowHideGui: enumAppCounter++,
VST_EnableMidiForTrack: enumAppCounter++,
VST_GetMidiDeviceList: enumAppCounter++,
VST_ScanForMidiDevices: enumAppCounter++,
IsOBSAvailable: enumAppCounter++,
StartMediaRecording: enumAppCounter++,
LaunchBroadcastSettings: enumAppCounter++,
SetRecordingOptionStartedByPeer: enumAppCounter++,
GetRecordingOptionStartedByPeer: enumAppCounter++,
SetAudioRecordingPreference: enumAppCounter++,
GetAudioRecordingPreference: enumAppCounter++,
PeerStopRecording: enumAppCounter++,
FrontStopRecording: enumAppCounter++,
GetCurrentRecordingId: enumAppCounter++,
});
function setupWebSocketConnection() {
const baseUrl = "ws://localhost:3060";
logger.log(
"[asyncJamClient] connecting to WebSocket server at " + baseUrl + "."
);
const socket = new WebSocket(baseUrl);
socket.onclose = function (event) {
logger.error("[asyncJamClient] QWebChannel websocket closed");
if (event.code != 1000) {
// Error code 1000 means that the connection was closed normally.
// Try to reconnect.
if (!navigator.onLine) {
//alert("You are offline. Please connect to the Internet and try again.");
}
}
};
socket.onerror = function (error) {
logger.error("[asyncJamClient] QWebChannel websocket error: " + error);
};
socket.onopen = function () {
logger.log(
"[asyncJamClient] WebSocket connected, setting up QWebChannel."
);
const skipLogMethods = [
'getConnectionDetail'
]
const displayLogMethod = [
]
new QWebChannel(socket, function (channel) {
jkfrontendchannel = channel.objects.jkfrontendchannel;
if (jkfrontendchannel) {
window.isWebChannelReady = true;
let deferred;
try {
jkfrontendchannel.sendText.connect(function (message) {
// logger.log(
// "[asyncJamClient] Message received via QWebChannel: " +
// message
// );
//handle Method Not Implemented"
if (
typeof resp === "object" &&
resp[0] === "Method Not Implemented"
) {
//throw new Error("Method Not Implemented");
deferred.resolve(null); //return null value
} else {
let msg = JSON.parse(message);
let req_id = msg.request_id; //frontend originated request
let response = msg.response;
let evt_id = msg.event_id; //backend originated async event
let methodName = msg.method_name;
deferred = deferredQueue.find((d) => {
return d.request_id === req_id;
});
if (deferred) {
if(skipLogMethods.length > 0 && skipLogMethods.includes(methodName)){
}else{
if(displayLogMethod.includes(methodName)){
logger.log(
"[asyncJamClient] Message received via QWebChannel: " +
msg
);
}
}
deferred.resolve(response);
//remove this deferred object from queue
deferredQueue = deferredQueue.filter(
(d) => d.request_id !== deferred.request_id
);
} else if (evt_id) {
let method = Object.keys(response)[0]
// logger.log("[asyncJamClient] event received:", evt_id.toString(), Object.keys(response)[0])
// if(evt_id.toString() === '3012'){
// alert(evt_id.toString())
// }
switch (evt_id.toString()) {
case '3006': //execute_script
if(!response['execute_script'].match('HandleBridgeCallback2')){
//logger.log(`[asyncJamClient] 3006 execute_script: ${response['execute_script']}`);
}
try {
eval(response['execute_script']);
} catch (error) {
logger.log(`[asyncJamClient] error: execute_script: ${response['execute_script']}`);
logger.log(error);
}
break;
case '3007': //message
//logger.log(`[asyncJamClient] 3007 message: ${response['message']}`);
try {
const msg = response['message'];
const clientId = response['targetClientID'];
context.JK.JamServer.sendP2PMessage(clientId, msg)
} catch (error) {
logger.log(`[asyncJamClient] error: sendP2PMessage: ${response['message']}`);
logger.log(error);
}
break;
case '3010': //JKVideoSession
logger.log(`[asyncJamClient] 3010 JKVideoSession: ${response['JKVideoSession']['connect']}`);
const vidConnect = response['JKVideoSession']['connect'];
context.ExternalVideoActions.setVideoEnabled(vidConnect);
context.JK.videoIsOngoing = vidConnect;
break;
case '3011': //AudioFormatChangeEvent
logger.log(`[asyncJamClient] 3011 AudioFormatChangeEvent: ${response['AudioFormat']}`);
const audioFormat = response['AudioFormat']
context.RecordingActions.audioRecordingFormatChanged(`.${audioFormat}`)
break;
case '3012': //customUrl
const customUrl = response['CustomUrl']
//if localStorage is available and has customUrl key, remove it
if(localStorage){
if(localStorage.getItem('customUrl')){
localStorage.removeItem('customUrl')
}
//now set the customUrl which received from backend
if(customUrl){
const httpUrl = window.location.protocol + '//' + customUrl;
const customUrlHandler = new JK.CustomUrlHandler();
if(customUrlHandler.isValidUrl(httpUrl)){
localStorage.setItem('customUrl', httpUrl);
if(context.JK.currentUserId){
window.location.href = httpUrl;
}
}else{
logger.log(`[asyncJamClient] invalid customUrl: ${httpUrl}`);
}
}
}
break;
default:
break;
}
}
}
});
//TODO: handle method does not exist
} catch (e) {
logger.log(
"[asyncJamClient] Error when receving message via QWebChannel"
);
if (deferred) {
deferred.reject(e.message);
deferred = null;
}
Bugsnag.notify(e, function(event){
event.severity = 'info'
event.context = 'asyncJamClient'
event.setUser(gon.user_id, gon.user_email, gon.user_name)
});
}
}
});
};
}
function waitForOpenConnection(){
return new Promise((resolve, reject) => {
const maxNumberOfAttempts = 10
const intervalTime = 200 //ms
let currentAttempt = 0
const interval = setInterval(() => {
if (currentAttempt > maxNumberOfAttempts - 1) {
clearInterval(interval)
reject(new Error('Maximum number of attempts exceeded'))
} else if (jkfrontendchannel) {
clearInterval(interval)
resolve()
}
currentAttempt++
}, intervalTime)
})
}
async function sendWhenReady(prop, args){
if (jkfrontendchannel) {
return sendMessage(prop, args)
}else{
try {
await waitForOpenConnection()
return sendMessage(prop, args)
} catch (err) { console.error(err) }
}
}
function sendMessage(prop, args){
let appMessage = new Object();
appMessage.request_id = ++request_id;
appMessage.arguments = Array.from(args) || [];
let method = JKFrontendMethods[prop];
appMessage.method = method;
let deferred = new Deferred(appMessage.request_id);
const skipLogMethods = [
]
const displayLogMethod = [
// 'SessionSetTrackVolumeData'
]
if(skipLogMethods.length > 0 && skipLogMethods.includes(prop)){
}else{
if(displayLogMethod.includes(prop)){
logger.log(
"[asyncJamClient] diverting to backend:",
prop,
appMessage
);
}
}
if (jkfrontendchannel) {
try {
jkfrontendchannel.receiveText(JSON.stringify(appMessage));
deferredQueue.push(deferred);
return deferred.promise;
} catch (e) {
logger.error(
"[asyncJamClient] Native app not connected",
e.message
);
deferred.reject('Native app not connected')
return deferred.promise;
}
} else {
logger.info(
"[asyncJamClient] jkfrontendchannel is not ready yet"
);
deferred.reject('frontendchannel is not ready yet')
return deferred.promise;
}
}
function setupAsyncProxy() {
let proxy;
const handler = {
get(target, prop, receiver) {
//const origMethod = target[prop];
//console.log('[asyncJamClient] get:', target, prop);
return function (...args) {
// let result = origMethod.apply(this, args);
// console.log(prop + JSON.stringify(args)+ ' -> ' + JSON.stringify(result));
// return result;
return sendWhenReady(prop, arguments)
};
},
};
proxy = new Proxy(self, handler);
logger.log(
"[asyncJamClient] Connected to WebChannel, ready to send/receive messages!"
);
return proxy;
}
setupWebSocketConnection();
return setupAsyncProxy();
};
})(window, jQuery);

View File

@ -23,8 +23,8 @@
context.location = "/client#"; // leaveSession will be called in beforeHide below
}
function onStunEvent() {
var testResults = context.jamClient.NetworkTestResult();
async function onStunEvent() {
var testResults = await context.jamClient.NetworkTestResult();
$.each(testResults, function (index, val) {
if (val.bStunFailed) {
@ -49,8 +49,7 @@
}
function alertCallback(type, text) {
async function alertCallback(type, text) {
function timeCallback() {
var start = new Date();
setTimeout(function() {
@ -64,6 +63,7 @@
timeCallback();
logger.debug("alert callback", type, text);
console.log("alert callback", type, text);
var alertData = $.extend({}, ALERT_TYPES[type]);
@ -129,7 +129,7 @@
else if(type === ALERT_NAMES.RECORD_PLAYBACK_STATE) {
//if(context.JK.CurrentSessionModel)
// context.JK.CurrentSessionModel.onPlaybackStateChange(type, text);
context.MediaPlaybackActions.playbackStateChange(text);
await context.MediaPlaybackActions.playbackStateChange(text);
}
else if(type === ALERT_NAMES.VIDEO_WINDOW_OPENED) {
context.VideoActions.videoWindowOpened()
@ -150,8 +150,8 @@
}
}
function initialize() {
context.jamClient.SessionSetAlertCallback("JK.AlertCallback");
async function initialize() {
await context.jamClient.SessionSetAlertCallback("JK.AlertCallback");
}
this.initialize = initialize;

View File

@ -153,7 +153,7 @@
// refreshes the currently active tab
function renderActive() {
//console.log("_DEBUG_ renderActive isAdmin: " + isAdmin + " isMember: " + isMember);
if (isMember) {
$("#btn-follow-band").hide();
$("#btn-edit-band-profile").show();
@ -549,6 +549,7 @@
error: app.ajaxError
})
.done(function(response) {
//console.log("_DEBUG_ determineMembership response: " + JSON.stringify(response));
isAdmin = isMember = false;
$.each(response, function(index, val) {
if (val.id === context.JK.currentUserId) {

View File

@ -197,7 +197,7 @@
}
function renderErrors(errors) {
logger.debug("Band setup errors: ", errors)
console.log("Band setup errors: ", errors)
var name = context.JK.format_errors("name", errors);
var country = context.JK.format_errors("country", errors);
var state = context.JK.format_errors("state", errors);
@ -205,6 +205,8 @@
var biography = context.JK.format_errors("biography", errors);
var website = context.JK.format_errors("website", errors);
var genres = context.JK.format_errors("genres", errors);
var hourly_rate = context.JK.format_errors("hourly_rate", errors);
var gig_minimum = context.JK.format_errors("gig_minimum", errors);
if(name) $("#band-name").closest('div.field').addClass('error').end().after(name);
if(country) $("#band-country").closest('div.field').addClass('error').end().after(country);
@ -213,6 +215,8 @@
if(biography) $("#band-biography").closest('div.field').addClass('error').end().after(biography);
if(website) $("#band-website").closest('div.field').addClass('error').end().after(website);
if(genres) $("#band-genres").closest('div.field').addClass('error').end().after(genres);
if(hourly_rate) $("#hourly-rate").closest('div.field').addClass('error').end().after(hourly_rate);
if(gig_minimum) $("#gig-minimum").closest('div.field').addClass('error').end().after(gig_minimum);
}
function buildBand() {
@ -402,6 +406,7 @@
function loadBandDetails() {
rest.getBand(bandId).done(function (band) {
console.log("Band details: ", band)
$("#band-name").val(band.name);
$("#band-website").val(band.website);
$("#band-biography").val(band.biography);
@ -411,21 +416,27 @@
concertCount.val(band.concert_count)
if (band.add_new_members){
$("#new-member-no").iCheck('check').attr('checked', 'checked')
} else {
$("#new-member-yes").iCheck('check').attr('checked', 'checked')
$("#new-member-no").iCheck('uncheck').removeAttr('checked')
} else {
$("#new-member-no").iCheck('check').attr('checked', 'checked')
$("#new-member-yes").iCheck('uncheck').removeAttr('checked')
}
if (band.paid_gigs) {
$("#paid-gigs-no").iCheck('check').attr('checked', 'checked')
} else {
$("#paid-gigs-yes").iCheck('check').attr('checked', 'checked')
$("#paid-gigs-no").iCheck('uncheck').removeAttr('checked')
} else {
$("#paid-gigs-no").iCheck('check').attr('checked', 'checked')
$("#paid-gigs-yes").iCheck('uncheck').removeAttr('checked')
}
if (band.free_gigs) {
$("#free-gigs-no").iCheck('check').attr('checked', 'checked')
} else {
$("#free-gigs-yes").iCheck('check').attr('checked', 'checked')
$("#free-gigs-no").iCheck('uncheck').removeAttr('checked')
} else {
$("#free-gigs-no").iCheck('check').attr('checked', 'checked')
$("#free-gigs-yes").iCheck('uncheck').removeAttr('checked')
}
$('#touring-option').val(band.touring_option ? 'yes' : 'no')

View File

@ -149,7 +149,7 @@
}
// called from sidebar when messages come in
function chatMessageReceived(payload) {
async function chatMessageReceived(payload) {
if (fullyInitialized) {
if (isChatPanelVisible()) {
@ -157,7 +157,7 @@
else {
highlightCount();
incrementChatCount();
context.jamClient.UserAttention(true);
await context.jamClient.UserAttention(true);
}
}
}

View File

@ -18,7 +18,7 @@
function cancelUpdate(e) {
if ((e.ctrlKey || e.metaKey) && e.keyCode == 78) {
logger.debug("update canceled!");
console.log("update canceled!");
app.layout.closeDialog('client-update');
app.clientUpdating = false;
}
@ -82,7 +82,7 @@
/***************************************/
function clientUpdateDownloadProgress(bytesReceived, bytesTotal, downloadSpeedMegSec, timeRemaining) {
// this fires way too many times to leave in. uncomment if debugging update feature
//logger.debug("bytesReceived: " + bytesReceived, ", bytesTotal: " + bytesTotal, ", downloadSpeed: " + downloadSpeedMegSec, ", timeRemaining: " + timeRemaining + ", updateSize: " + updateSize);
//console.log("bytesReceived: " + bytesReceived, ", bytesTotal: " + bytesTotal, ", downloadSpeed: " + downloadSpeedMegSec, ", timeRemaining: " + timeRemaining + ", updateSize: " + updateSize);
bytesReceived = Number(bytesReceived)
bytesTotal = Number(bytesTotal)
@ -93,7 +93,7 @@
}
function clientUpdateDownloadSuccess(updateLocation) {
logger.debug("client update downloaded successfully to: " + updateLocation);
console.log("client update downloaded successfully to: " + updateLocation);
updateClientUpdateDialog("update-proceeding");
@ -112,12 +112,12 @@
}
function clientUpdateLaunchSuccess(userTimeToRead) {
async function clientUpdateLaunchSuccess(userTimeToRead) {
if(userTimeToRead === undefined) {
userTimeToRead = 1000; // older clients didn't pass this in, and exit very quickly
}
logger.debug("client update launching in: " + userTimeToRead);
console.log("client update launching in: " + userTimeToRead);
// set timer to update countdown
var rounded = Math.round(userTimeToRead / 1000);
@ -135,7 +135,7 @@
}
}, rounded * 1000);
updateClientUpdateDialog("update-restarting", {countdown: rounded, os: context.JK.GetOSAsString()});
updateClientUpdateDialog("update-restarting", {countdown: rounded, os: await context.JK.GetOSAsString()});
}
function clientUpdateLaunchFailure(errorMsg) {
@ -145,7 +145,7 @@
}
function clientUpdateLaunchStatuses(statuses) {
logger.debug("client update launch statuses");
console.log("client update launch statuses");
if (statuses) {
for (var i = 0; i < statuses.length; i++) {
@ -155,7 +155,7 @@
}
function clientUpdateLaunchStatusChange(done, status) {
logger.debug("client update launch status change. starting=" + done + ", status=" + status);
console.log("client update launch status change. starting=" + done + ", status=" + status);
if (!done) {
var $ellipses = $('<span class="ellipses">.</span>');
@ -201,19 +201,24 @@
}
}
function runCheck(product, version, uri, size, currentVersion) {
async function runCheck(product, version, uri, size, currentVersion) {
if (app.clientUpdating) {
logger.debug("client is already updating; skipping")
console.log("client is already updating; skipping")
return
}
if(currentVersion === undefined) {
currentVersion = context.jamClient.ClientUpdateVersion();
console.log("runCheck: product , version", product, version)
// check kill switch before all other logic
if (!gon.check_for_client_updates) {
console.log("runCheck: skipping client update because the server is telling us not to")
return;
}
if(currentVersion === undefined) {
currentVersion = await context.jamClient.ClientUpdateVersion() //.then(function(currentVersion){
if (!forceShow && (currentVersion == null || currentVersion.indexOf("Compiled")) > -1) {
// this is a developer build; it doesn't make much sense to do an packaged update, so skip
logger.debug("skipping client update check because this is a development build ('" + currentVersion + "')")
console.log("skipping client update check because this is a development build ('" + currentVersion + "')")
return;
}
@ -221,9 +226,10 @@
if (currentVersion.indexOf('"') == 0 && currentVersion.lastIndexOf('"') == currentVersion.length - 1) {
currentVersion = currentVersion.substring(1, currentVersion.length - 1);
}
//});
}
logger.debug("our client version: " + currentVersion + ", server client version: " + version);
//console.log("_DEBUG_ our client version: " + currentVersion + ", server client version: " + version);
// test url in lieu of having a configured server with a client-update available
@ -233,7 +239,7 @@
updateSize = size;
if(context.SessionStore.inSession()) {
logger.debug("deferring client update because in session")
console.log("deferring client update because in session")
return;
}
@ -254,23 +260,23 @@
}
// check if updated is needed
function check() {
var os = context.JK.GetOSAsString();
async function check() {
var os = await context.jamClient.GetDetailedOS();
//os = 'Win32'
// check kill switch before all other logic
if (!gon.check_for_client_updates) {
logger.debug("skipping client update because the server is telling us not to")
console.log("skipping client update because the server is telling us not to")
return;
}
var product = "JamClient"
var currentVersion = context.jamClient.ClientUpdateVersion();
//var product = "JamClient"
var product = "JamClientModern"
var currentVersion = await context.jamClient.ClientUpdateVersion();
if (!forceShow && (currentVersion == null || currentVersion.indexOf("Compiled")) > -1) {
// this is a developer build; it doesn't make much sense to do an packaged update, so skip
logger.debug("skipping client update check because this is a development build ('" + currentVersion + "')")
console.log("skipping client update check because this is a development build ('" + currentVersion + "')")
return;
}
@ -283,7 +289,9 @@
type: "GET",
url: "/api/versioncheck?product=" + product + "&os=" + os,
success: function (response) {
runCheck(product, response.version, response.uri, response.size, currentVersion);
if(!jQuery.isEmptyObject(response)){
runCheck(product, response.version, response.uri, response.size, currentVersion);
}
},
error: function (jqXHR, textStatus, errorThrown) {
logger.error("Unable to do a client update check against /api/versioncheck");
@ -291,21 +299,61 @@
});
}
function startDownload(url) {
logger.debug("starting client updater download from: " + url);
async function isUpdateAvailable(){
//this should check if the current version is less than the server version
//if so, return true
//otherwise return false
var os = await context.jamClient.GetDetailedOS();
//os = 'Win32'
var product = "JamClientModern"
var currentVersion = await context.jamClient.ClientUpdateVersion();
if (!forceShow && (currentVersion == null || currentVersion.indexOf("Compiled")) > -1) {
// this is a developer build; it doesn't make much sense to do an packaged update, so skip
console.log("skipping client update check because this is a development build ('" + currentVersion + "')")
return false;
}
// # strange client oddity: remove quotes, if found, from start and finish of version.
if (currentVersion.indexOf('"') == 0 && currentVersion.lastIndexOf('"') == currentVersion.length - 1) {
currentVersion = currentVersion.substring(1, currentVersion.length - 1);
}
return new Promise((resolve, reject) => {
$.ajax({
type: "GET",
url: "/api/versioncheck?product=" + product + "&os=" + os,
success: function (response) {
if(!jQuery.isEmptyObject(response)){
// runCheck(product, response.version, response.uri, response.size, currentVersion);
var result = shouldUpdate(currentVersion, response.version);
resolve(result);
} else {
resolve(false);
}
},
error: function (jqXHR, textStatus, errorThrown) {
logger.error("Unable to do a client update check against /api/versioncheck");
resolve(false);
}
});
});
}
async function startDownload(url) {
console.log("starting client updater download from: " + url);
updateClientUpdateDialog("update-downloading")
context.jamClient.ClientUpdateStartDownload(url,
await context.jamClient.ClientUpdateStartDownload(url,
"JK.ClientUpdate.DownloadProgressCallback",
"JK.ClientUpdate.DownloadSuccessCallback",
"JK.ClientUpdate.DownloadFailureCallback");
}
function startUpdate(updaterFilePath) {
logger.debug("starting client update from: " + updaterFilePath)
async function startUpdate(updaterFilePath) {
console.log("starting client update from: " + updaterFilePath)
context.jamClient.ClientUpdateStartUpdate(updaterFilePath,
await context.jamClient.ClientUpdateStartUpdate(updaterFilePath,
"JK.ClientUpdate.LaunchUpdateSuccessCallback",
"JK.ClientUpdate.LaunchUpdateFailureCallback",
"JK.ClientUpdate.LaunchUpdateStatusesCallback",
@ -336,6 +384,7 @@
this.initialize = initialize;
this.check = check;
this.runCheck = runCheck;
this.isUpdateAvailable = isUpdateAvailable;
}
return this;

View File

@ -11,16 +11,30 @@ context.JK.ClientInit = class ClientInit
@ALERT_NAMES = context.JK.ALERT_NAMES;
@lastCheckedBroadcast = null
init: () =>
if context.gon.isNativeClient
this.nativeClientInit()
# init: () =>
# if context.gon.isNativeClient
# this.nativeClientInit()
context.JK.onBackendEvent(@ALERT_NAMES.WINDOW_OPEN_FOREGROUND_MODE, 'client_init', @watchBroadcast);
# context.JK.onBackendEvent(@ALERT_NAMES.WINDOW_OPEN_FOREGROUND_MODE, 'client_init', @watchBroadcast);
this.watchBroadcast()
# this.watchBroadcast()
if context.jamClient.RegisterSessionJoinLeaveRequestCallBack?
context.jamClient.RegisterSessionJoinLeaveRequestCallBack("SessionStore.handleJoinLeaveRequestCallback")
# if context.jamClient.RegisterSessionJoinLeaveRequestCallBack?
# context.jamClient.RegisterSessionJoinLeaveRequestCallBack("SessionStore.handleJoinLeaveRequestCallback")
init: `async function(){
if (context.gon.isNativeClient) {
await this.nativeClientInit();
}
context.JK.onBackendEvent(this.ALERT_NAMES.WINDOW_OPEN_FOREGROUND_MODE, 'client_init', this.watchBroadcast);
this.watchBroadcast();
//if (await context.jamClient.RegisterSessionJoinLeaveRequestCallBack != null) {
await context.jamClient.RegisterSessionJoinLeaveRequestCallBack("SessionStore.handleJoinLeaveRequestCallback");
//}
}`
checkBroadcast: () =>
promise = window.BroadcastActions.load.trigger()
@ -38,9 +52,15 @@ context.JK.ClientInit = class ClientInit
setTimeout(@checkBroadcast, 3000)
nativeClientInit: () =>
@gearUtils.bootstrapDefaultPlaybackProfile();
# nativeClientInit: () =>
# @gearUtils.bootstrapDefaultPlaybackProfile();
context.VideoActions.checkPromptConfigureVideo()
# context.VideoActions.checkPromptConfigureVideo()
nativeClientInit: `async function(){
await this.gearUtils.bootstrapDefaultPlaybackProfile();
return context.VideoActions.checkPromptConfigureVideo();
}`

View File

@ -146,8 +146,8 @@
});
$('#btn-driver-settings').unbind("click");
$('#btn-driver-settings').click(function () {
context.jamClient.TrackOpenControlPanel();
$('#btn-driver-settings').click(async function () {
await context.jamClient.TrackOpenControlPanel();
});
$('#btn-cancel-new-audio').unbind("click");
@ -156,10 +156,14 @@
$('#btn-error-ok').click(context.JK.showOverlay);
$('#btn-save-settings').unbind("click");
$('#btn-save-settings').click(saveSettings);
$('#btn-save-settings').click(async function(){
await saveSettings()
});
$('#btn-cancel-settings').unbind("click");
$('#btn-cancel-settings').click(cancelSettings);
$('#btn-cancel-settings').click(async function(){
await cancelSettings()
});
}
function _handleTrackInputAdd($selectedMusicInputs, selector) {
@ -262,14 +266,14 @@
return chatOtherUnassignedListCopy.length > 0 || chatOtherAssignedListCopy.length > 0;
}
function audioDriverChanged() {
async function audioDriverChanged() {
context.jamClient.TrackSetMusicDevice($('#audio-drivers').val());
await context.jamClient.TrackSetMusicDevice($('#audio-drivers').val());
logger.debug("Called TrackSetMusicDevice with " + $('#audio-drivers').val());
context.jamClient.TrackLoadAssignments();
initDialogData();
await context.jamClient.TrackLoadAssignments();
await initDialogData();
// refresh dialog
showVoiceChatPanel(true);
@ -319,8 +323,8 @@
});
}
function configureDriverSettingsButton() {
if (context.jamClient.TrackHasControlPanel()) {
async function configureDriverSettingsButton() {
if (await context.jamClient.TrackHasControlPanel()) {
$('#btn-driver-settings').show();
}
else {
@ -328,7 +332,7 @@
}
}
function showMusicAudioPanel(refreshLists) {
async function showMusicAudioPanel(refreshLists) {
_setInstructions('audio');
_activateTab('audio');
@ -336,11 +340,11 @@
$('#audio-drivers').empty();
// determine correct music device to preselect
var deviceId = context.jamClient.TrackGetMusicDeviceID();
var deviceId = await context.jamClient.TrackGetMusicDeviceID();
logger.debug("deviceId = " + deviceId);
// load Audio Driver dropdown
devices = context.jamClient.TrackGetDevices();
devices = await context.jamClient.TrackGetDevices();
logger.debug("Called TrackGetDevices with response " + JSON.stringify(devices));
var keys = Object.keys(devices);
@ -362,7 +366,7 @@
context.JK.dropdown($('#audio-drivers'));
if (deviceId === '') {
context.jamClient.TrackSetMusicDevice($('#audio-drivers').val());
await context.jamClient.TrackSetMusicDevice($('#audio-drivers').val());
}
configureDriverSettingsButton();
@ -384,7 +388,7 @@
context.JK.loadOptions($('#template-option').html(), $('#track1-input'), track1AudioInputChannels, "id", "name", -1);
// load Track 1 Instrument
var current_instrument = context.jamClient.TrackGetInstrument(ASSIGNMENT.TRACK1);
var current_instrument = await context.jamClient.TrackGetInstrument(ASSIGNMENT.TRACK1);
// if no instrument is stored on the backend, the user is opening this dialog for the first time after FTUE;
// initialize to the user's first instrument
@ -401,7 +405,7 @@
context.JK.loadOptions($('#template-option').html(), $('#track2-input'), track2AudioInputChannels, "id", "name", -1);
// load Track 2 Instrument
current_instrument = context.jamClient.TrackGetInstrument(ASSIGNMENT.TRACK2);
current_instrument = await context.jamClient.TrackGetInstrument(ASSIGNMENT.TRACK2);
context.JK.loadOptions($('#template-option').html(), $('#track2-instrument'), instrument_array, "id", "description", current_instrument);
// load Unused Outputs
@ -455,56 +459,56 @@
}
}
function initDialogData() {
_initMusicTabData();
_initVoiceChatTabData();
async function initDialogData() {
await _initMusicTabData();
await _initVoiceChatTabData();
}
function _initMusicTabData() {
inputUnassignedList = _loadList(ASSIGNMENT.UNASSIGNED, true, false);
async function _initMusicTabData() {
inputUnassignedList = await _loadList(ASSIGNMENT.UNASSIGNED, true, false);
//logger.debug("inputUnassignedList=" + JSON.stringify(inputUnassignedList));
track1AudioInputChannels = _loadList(ASSIGNMENT.TRACK1, true, false);
track1AudioInputChannels = await _loadList(ASSIGNMENT.TRACK1, true, false);
//logger.debug("track1AudioInputChannels=" + JSON.stringify(track1AudioInputChannels));
track2AudioInputChannels = _loadList(ASSIGNMENT.TRACK2, true, false);
track2AudioInputChannels = await _loadList(ASSIGNMENT.TRACK2, true, false);
//logger.debug("track2AudioInputChannels=" + JSON.stringify(track2AudioInputChannels));
outputUnassignedList = _loadList(ASSIGNMENT.UNASSIGNED, false, false);
outputAssignedList = _loadList(ASSIGNMENT.OUTPUT, false, false);
outputUnassignedList = await _loadList(ASSIGNMENT.UNASSIGNED, false, false);
outputAssignedList = await _loadList(ASSIGNMENT.OUTPUT, false, false);
}
function _initVoiceChatTabData() {
chatUnassignedList = _loadList(ASSIGNMENT.UNASSIGNED, true, false);
async function _initVoiceChatTabData() {
chatUnassignedList = await _loadList(ASSIGNMENT.UNASSIGNED, true, false);
//logger.debug("chatUnassignedList=" + JSON.stringify(chatUnassignedList));
chatAssignedList = _loadList(ASSIGNMENT.CHAT, true, false);
chatAssignedList = await _loadList(ASSIGNMENT.CHAT, true, false);
//logger.debug("chatAssignedList=" + JSON.stringify(chatAssignedList));
chatOtherUnassignedList = _loadList(ASSIGNMENT.UNASSIGNED, true, true);
chatOtherUnassignedList = await _loadList(ASSIGNMENT.UNASSIGNED, true, true);
//logger.debug("chatOtherUnassignedList=" + JSON.stringify(chatOtherUnassignedList));
chatOtherAssignedList = _loadList(ASSIGNMENT.CHAT, true, true);
chatOtherAssignedList = await _loadList(ASSIGNMENT.CHAT, true, true);
//logger.debug("chatOtherAssignedList=" + JSON.stringify(chatOtherAssignedList));
}
// TODO: copied in addTrack.js - refactor to common place
function _loadList(assignment, input, chat) {
async function _loadList(assignment, input, chat) {
var list = [];
// get data needed for listboxes
var channels = context.jamClient.TrackGetChannels();
var channels = await context.jamClient.TrackGetChannels();
var musicDevices = context.jamClient.TrackGetMusicDeviceNames(input);
var musicDevices = await context.jamClient.TrackGetMusicDeviceNames(input);
// SEE loadList function in TrackAssignGui.cpp of client code
$.each(channels, function (index, val) {
$.each(channels, async function (index, val) {
if (input !== val.input) {
return;
}
var currAssignment = context.jamClient.TrackGetAssignment(val.id, val.input);
var currAssignment = await context.jamClient.TrackGetAssignment(val.id, val.input);
if (assignment !== currAssignment) {
return;
}
@ -512,14 +516,15 @@
// logger.debug("channel id=" + val.id + ", channel input=" + val.input + ", channel assignment=" + currAssignment +
// ", channel name=" + val.name + ", channel type=" + val.device_type + ", chat=" + val.chat);
var os = context.jamClient.GetOSAsString();
var os = await context.jamClient.GetOSAsString();
if (os === context.JK.OS.WIN32) {
if (chat && ($.inArray(val.device_id, musicDevices) > -1 || context.jamClient.TrackIsMusicDeviceType(val.device_type))) {
if (chat && ($.inArray(val.device_id, musicDevices) > -1 || await context.jamClient.TrackIsMusicDeviceType(val.device_type))) {
return;
}
}
else {
if (chat && ($.inArray(val.device_id, musicDevices) > -1 || !context.jamClient.TrackIsMusicDeviceType(val.device_type))) {
var trackIsType = await context.jamClient.TrackIsMusicDeviceType(val.device_type)
if (chat && ($.inArray(val.device_id, musicDevices) > -1 || !trackIsType)) {
return;
}
}
@ -538,7 +543,7 @@
return list;
}
function saveSettings() {
async function saveSettings() {
if (!context.JK.verifyNotRecordingForTrackChange(app)) {
return;
}
@ -551,29 +556,29 @@
return;
}
saveAudioSettings();
saveVoiceChatSettings();
await saveAudioSettings();
await saveVoiceChatSettings();
context.jamClient.TrackSaveAssignments();
await context.jamClient.TrackSaveAssignments();
originalDeviceId = $('#audio-drivers').val();
app.layout.closeDialog('configure-audio');
}
function saveAudioSettings() {
async function saveAudioSettings() {
context.jamClient.TrackSetMusicDevice($('#audio-drivers').val());
await context.jamClient.TrackSetMusicDevice($('#audio-drivers').val());
// UNASSIGNED INPUTS
$('#audio-inputs-unused > option').each(function () {
$('#audio-inputs-unused > option').each(async function () {
logger.debug("Marking " + this.value + " as unassigned input.");
context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.UNASSIGNED);
await context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.UNASSIGNED);
});
// TRACK 1 INPUTS
$('#track1-input > option').each(function () {
$('#track1-input > option').each(async function () {
logger.debug("Saving track 1 input = " + this.value);
context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK1);
await context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK1);
});
// TRACK 1 INSTRUMENT
@ -581,15 +586,15 @@
var instrumentText = $('#track1-instrument > option:selected').text().toLowerCase();
logger.debug("Saving track 1 instrument = " + instrumentVal);
context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK1, instrumentVal);
await context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK1, instrumentVal);
// TRACK 2 INPUTS
var track2Selected = false;
$('#track2-input > option').each(function () {
$('#track2-input > option').each(async function () {
track2Selected = true;
logger.debug("Saving track 2 input = " + this.value);
context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK2);
await context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK2);
});
if (track2Selected) {
@ -598,66 +603,66 @@
instrumentText = $('#track2-instrument > option:selected').text().toLowerCase();
logger.debug("Saving track 2 instrument = " + instrumentVal);
context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK2, instrumentVal);
await context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK2, instrumentVal);
}
else {
// track 2 was removed
if (myTrackCount === 2) {
logger.debug("Deleting track " + myTracks[1].trackId);
context.jamClient.TrackSetCount(1);
await context.jamClient.TrackSetCount(1);
//sessionModel.deleteTrack(sessionId, myTracks[1].trackId);
}
}
// UNASSIGNED OUTPUTS
$('#audio-output-unused > option').each(function () {
$('#audio-output-unused > option').each(async function () {
logger.debug("Marking " + this.value + " as unassigned output.");
context.jamClient.TrackSetAssignment(this.value, false, ASSIGNMENT.UNASSIGNED);
await context.jamClient.TrackSetAssignment(this.value, false, ASSIGNMENT.UNASSIGNED);
});
// OUTPUT
$('#audio-output-selection > option').each(function () {
$('#audio-output-selection > option').each(async function () {
logger.debug("Saving session audio output = " + this.value);
context.jamClient.TrackSetAssignment(this.value, false, ASSIGNMENT.OUTPUT);
await context.jamClient.TrackSetAssignment(this.value, false, ASSIGNMENT.OUTPUT);
});
}
function saveVoiceChatSettings() {
async function saveVoiceChatSettings() {
var voiceChatType = isChatInputSpecified();
originalVoiceChat = voiceChatType;
logger.debug("Calling TrackSetChatEnable with value = " + voiceChatType);
context.jamClient.TrackSetChatEnable(voiceChatType == VOICE_CHAT.CHAT ? true : false);
await context.jamClient.TrackSetChatEnable(voiceChatType == VOICE_CHAT.CHAT ? true : false);
if (voiceChatType == VOICE_CHAT.CHAT) {
// UNASSIGNED VOICE CHAT
$('#voice-inputs-unused > option').each(function () {
$('#voice-inputs-unused > option').each(async function () {
logger.debug("Marking " + this.value + " as unassigned voice input.");
context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.UNASSIGNED);
await context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.UNASSIGNED);
});
// VOICE CHAT INPUT
$("#voice-inputs-selection > option").each(function () {
$("#voice-inputs-selection > option").each(async function () {
logger.debug("Saving chat input = " + this.value);
context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.CHAT);
await context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.CHAT);
});
}
// make sure any previously assigned chat devices are marked as unassigned
else if (voiceChatType == VOICE_CHAT.NO_CHAT) {
// chat devices that were assigned
$.each(chatOtherAssignedList, function (index, val) {
$.each(chatOtherAssignedList, async function (index, val) {
logger.debug("Marking " + val.id + " as unassigned voice input.");
context.jamClient.TrackSetAssignment(val.id, true, ASSIGNMENT.UNASSIGNED);
await context.jamClient.TrackSetAssignment(val.id, true, ASSIGNMENT.UNASSIGNED);
});
}
}
function cancelSettings() {
async function cancelSettings() {
logger.debug("Cancel settings");
// reset to original device ID
context.jamClient.TrackSetMusicDevice(originalDeviceId);
await context.jamClient.TrackSetMusicDevice(originalDeviceId);
$('#voice-chat-type').val(originalVoiceChat);
@ -759,10 +764,10 @@
return isValid;
}
function _setInstructions(type) {
async function _setInstructions(type) {
var $instructions = $('#instructions', 'div[layout-id="configure-audio"]');
if (type === 'audio') {
var os = context.jamClient.GetOSAsString();
var os = await context.jamClient.GetOSAsString();
$instructions.html(configure_audio_instructions[os]);
}
else if (type === 'voice') {
@ -774,18 +779,18 @@
return $('#voice-inputs-selection option').size() > 0 ? VOICE_CHAT.CHAT : VOICE_CHAT.NO_CHAT;
}
function _init() {
async function _init() {
// load instrument array for populating listboxes, using client_id in instrument_map as ID
instrument_array = context.JK.listInstruments();
originalVoiceChat = context.jamClient.TrackGetChatEnable() ? VOICE_CHAT.CHAT : VOICE_CHAT.NO_CHAT;
originalVoiceChat = await context.jamClient.TrackGetChatEnable() ? VOICE_CHAT.CHAT : VOICE_CHAT.NO_CHAT;
$('#voice-chat-type').val(originalVoiceChat);
originalDeviceId = context.jamClient.TrackGetMusicDeviceID();
originalDeviceId = await context.jamClient.TrackGetMusicDeviceID();
context.jamClient.TrackLoadAssignments();
initDialogData();
await context.jamClient.TrackLoadAssignments();
await initDialogData();
var $option1 = $('#voice-chat-type > option[value="1"]');

View File

@ -155,8 +155,8 @@
// inputChannelFilter is an optional argument that is used by the Gear Wizard.
// basically, if an input channel isn't in there, it's not going to be displayed
function loadChannels(forceInputsToUnassign, inputChannelFilter) {
var musicPorts = jamClient.FTUEGetChannels();
async function loadChannels(forceInputsToUnassign, inputChannelFilter) {
var musicPorts = await jamClient.FTUEGetChannels();
$unassignedInputsHolder.empty();
$unassignedOutputsHolder.empty();
@ -370,33 +370,44 @@
return true;
}
function save(state) {
async function save(state) {
context._.each(state.unassignedChannels, function(unassignedChannelId) {
context.jamClient.TrackSetAssignment(unassignedChannelId, true, ASSIGNMENT.UNASSIGNED);
});
//context._.each(state.unassignedChannels, async function(unassignedChannelId) {
for(const unassignedChannelId of state.unassignedChannels){
await context.jamClient.TrackSetAssignment(unassignedChannelId, true, ASSIGNMENT.UNASSIGNED);
}
//});
// save input/tracks
context._.each(state.tracks, function(track, index) {
//context._.each(state.tracks, async function(track, index) {
for(let index = 0; index < state.tracks.length; index++) {
var track = state.tracks[index];
var trackNumber = index + 1;
context._.each(track.channels, function(channelId) {
context.jamClient.TrackSetAssignment(channelId, true, trackNumber);
});
//context._.each(track.channels, async function(channelId) {
for(const channelId of track.channels){
await context.jamClient.TrackSetAssignment(channelId, true, trackNumber);
}
//});
logger.debug("context.jamClient.TrackSetInstrument(trackNumber, track.instrument_id)", trackNumber, track.instrument_id);
context.jamClient.TrackSetInstrument(trackNumber, context.JK.instrument_id_to_instrument[track.instrument_id].client_id);
});
await context.jamClient.TrackSetInstrument(trackNumber, context.JK.instrument_id_to_instrument[track.instrument_id].client_id);
}
//});
// save outputs
context._.each(state.outputs, function(output, index) {
context._.each(output.channels, function(channelId) {
context.jamClient.TrackSetAssignment(channelId, true, ASSIGNMENT.OUTPUT);
});
});
//context._.each(state.outputs, function(output, index) {
for(let index = 0; index < state.outputs.length; index ++) {
let output = state.outputs[index];
//context._.each(output.channels, async function(channelId) {
for (const channelId of output.channels) {
await context.jamClient.TrackSetAssignment(channelId, true, ASSIGNMENT.OUTPUT);
}
//});
}
//});
var result = context.jamClient.TrackSaveAssignments();
var result = await context.jamClient.TrackSaveAssignments();
if(!result || result.length == 0) {
// success
@ -408,20 +419,25 @@
}
}
function loadTrackInstruments(forceInputsToUnassign) {
async function loadTrackInstruments(forceInputsToUnassign) {
var $trackInstruments = $instrumentsHolder.find('.track-instrument');
context._.each($trackInstruments, function(trackInstrument) {
//context._.each($trackInstruments, async function(trackInstrument) {
for(let i = 0; i < $trackInstruments.length; i++) {
var trackInstrument = $trackInstruments[i];
var $trackInstrument = $(trackInstrument);
var trackIndex = parseInt($trackInstrument.attr('data-num')) + 1;
var clientInstrument = context.jamClient.TrackGetInstrument(trackIndex);
var clientInstrument = await context.jamClient.TrackGetInstrument(trackIndex);
var instrument = context.JK.client_to_server_instrument_map[clientInstrument];
$trackInstrument.instrumentSelectorSet(instrument ? instrument.server_id : instrument);
});
}
//});
}
function trySave() {
@ -440,9 +456,9 @@
return saved;
}
function reset(forceInputsToUnassign, inputChannelFilter) {
async function reset(forceInputsToUnassign, inputChannelFilter) {
loadChannels(forceInputsToUnassign, inputChannelFilter);
loadTrackInstruments(forceInputsToUnassign);
await loadTrackInstruments(forceInputsToUnassign);
}
function unassignOutputChannel($channel) {

View File

@ -26,8 +26,8 @@
// inputChannelFilter is an optional argument that is used by the Gear Wizard.
// basically, if an input channel isn't in there, it's not going to be displayed
function loadChannels(forceInputsToUnassign, inputChannelFilter) {
var musicPorts = jamClient.FTUEGetChannels();
async function loadChannels(forceInputsToUnassign, inputChannelFilter) {
var musicPorts = await jamClient.FTUEGetChannels();
$unassignedInputsHolder.empty();
$unassignedOutputsHolder.empty();
@ -177,33 +177,45 @@
return true;
}
function save(state) {
async function save(state) {
context._.each(state.unassignedChannels, function(unassignedChannelId) {
context.jamClient.TrackSetAssignment(unassignedChannelId, true, ASSIGNMENT.UNASSIGNED);
});
//context._.each(state.unassignedChannels, async function(unassignedChannelId) {
for (const unassignedChannelId of state.unassignedChannels) {
await context.jamClient.TrackSetAssignment(unassignedChannelId, true, ASSIGNMENT.UNASSIGNED);
}
//});
// save input/tracks
context._.each(state.tracks, function(track, index) {
//context._.each(state.tracks, async function(track, index) {
for (let index = 0; index < state.tracks; index++) {
var track = state.tracks[index];
var trackNumber = index + 1;
context._.each(track.channels, function(channelId) {
context.jamClient.TrackSetAssignment(channelId, true, trackNumber);
});
//context._.each(track.channels, async function(channelId) {
for (const channelId of track.channels) {
await context.jamClient.TrackSetAssignment(channelId, true, trackNumber);
}
//});
logger.debug("context.jamClient.TrackSetInstrument(trackNumber, track.instrument_id)", trackNumber, track.instrument_id);
context.jamClient.TrackSetInstrument(trackNumber, context.JK.instrument_id_to_instrument[track.instrument_id].client_id);
});
await context.jamClient.TrackSetInstrument(trackNumber, context.JK.instrument_id_to_instrument[track.instrument_id].client_id);
}
//});
// save outputs
context._.each(state.outputs, function(output, index) {
context._.each(output.channels, function(channelId) {
context.jamClient.TrackSetAssignment(channelId, true, ASSIGNMENT.OUTPUT);
});
});
//context._.each(state.outputs, async function(output, index) {
for(let index = 0; index < state.outputs.length; index++) {
let output = state.outputs[index];
//context._.each(output.channels, async function(channelId) {
for(const channelId of output.channels) {
await context.jamClient.TrackSetAssignment(channelId, true, ASSIGNMENT.OUTPUT);
}
//});
}
//});
var result = context.jamClient.TrackSaveAssignments();
var result = await context.jamClient.TrackSaveAssignments();
if(!result || result.length == 0) {
// success
@ -215,20 +227,26 @@
}
}
function loadTrackInstruments(forceInputsToUnassign) {
async function loadTrackInstruments(forceInputsToUnassign) {
var $trackInstruments = $instrumentsHolder.find('.track-instrument');
context._.each($trackInstruments, function(trackInstrument) {
//context._.each($trackInstruments, async function(trackInstrument) {
for(var i = 0; i < $trackInstruments.length; i++){
var trackInstrument = $trackInstruments[i];
var $trackInstrument = $(trackInstrument);
var trackIndex = parseInt($trackInstrument.attr('data-num')) + 1;
var clientInstrument = context.jamClient.TrackGetInstrument(trackIndex);
var clientInstrument = await context.jamClient.TrackGetInstrument(trackIndex);
var instrument = context.JK.client_to_server_instrument_map[clientInstrument];
$trackInstrument.instrumentSelectorSet(instrument ? instrument.server_id : instrument);
});
}
//});
}
function trySave() {
@ -247,9 +265,9 @@
return saved;
}
function reset(forceInputsToUnassign, inputChannelFilter) {
async function reset(forceInputsToUnassign, inputChannelFilter) {
loadChannels(forceInputsToUnassign, inputChannelFilter);
loadTrackInstruments(forceInputsToUnassign);
await loadTrackInstruments(forceInputsToUnassign);
}
function unassignOutputChannel($channel) {

View File

@ -116,7 +116,7 @@
return isValid;
}
function submitForm(evt) {
async function submitForm(evt) {
evt.preventDefault();
if(!gon.isNativeClient) {
@ -136,7 +136,7 @@
}
// if for some reason there are 0 tracks, show FTUE
var tracks = context.JK.TrackHelpers.getUserTracks(context.jamClient);
var tracks = await context.JK.TrackHelpers.getUserTracks(context.jamClient);
if(tracks.length == 0) {
logger.error("we should never have 0 tracks and have gotten this far. Launch FTUE is the best we can do right now")
// If user hasn't completed FTUE - do so now.
@ -172,7 +172,7 @@
if ($('#band-list option:selected').val() !== '') {
data.band = $('#band-list option:selected').val();
}
data.audio_latency = context.jamClient.FTUEGetExpectedLatency().latency;
data.audio_latency = await context.jamClient.FTUEGetExpectedLatency().latency;
// 1. If no previous session data, a single stereo track with the
// top instrument in the user's profile.

View File

@ -0,0 +1,139 @@
(function (context, $) {
"use strict";
context.JK = context.JK || {};
context.JK.CustomUrlHandler = function () {
var hashchangeEvent;
var loadEvent;
function handleCustomUrlScheme(customUrl) {
var maxAttempts = 10;
//TODO: show a notification while waiting for the screen to load
//extract the hash from the custom URL passed in
var url = new URL(customUrl);
var hash = url.hash;
if (hash) { // if the hash contains the custom yes flag
var screenLoadInterval = setInterval(() => {
//handle create session. #/createSession is a valid hash. switch to the createSession screen and handle creating a session from the custom URL
if (hash.includes("#/createSession/")) { // if the hash contains the createSession flag
if(context.SessionStore && context.SessionStore.inSession()){
// clearInterval(screenLoadInterval);
// return;
}else{
console.log("attempting to create session", maxAttempts);
if (JK.createScheduledSessionScreen && JK.CreateScheduledSessionDataIsLoaded) { // if the createScheduledSessionScreen is loaded
JK.createScheduledSessionScreen.createSessionByCustomUrlScheme(hash); // this will create a session
clearInterval(screenLoadInterval);
} else {
console.log("attempting to create session. ", maxAttempts);
maxAttempts--;
if (maxAttempts <= 0) {
clearInterval(screenLoadInterval);
}
}
}
}
//handle join session. there is no joinSession screen. JK.SessionUtils is a helper class that handles joining a session
if (hash.includes("#/joinSession/")) { // if the hash contains the joinSession flag
if (JK.SessionUtils) { // if the SessionUtils is loaded
JK.SessionUtils.joinSessionFromCustomUrlScheme(hash);
clearInterval(screenLoadInterval);
} else {
console.log("attempting to join session", maxAttempts);
maxAttempts--;
if (maxAttempts <= 0) {
clearInterval(screenLoadInterval);
}
}
}
}, 1000); // check every second
}
}
function isValidUrl(customUrl) {
if (!customUrl) {
return false;
}
try {
var url = new URL(customUrl);
var hash = url.hash;
//if the customUrl is valid, return true
if (hash.includes("#/createSession/") || hash.includes("#/joinSession/")) {
return true;
}
}catch (e) {
return false;
}
return false
}
function getCustomUrl() {
//get customUrl from local storage
if (localStorage && localStorage.getItem("customUrl")) {
try{
return decodeURIComponent(localStorage.getItem("customUrl"));
}
catch(e){
console.error("error decoding customUrl", e);
return null;
}
}
return null;
}
function handle() {
//clear the event listeners
if (hashchangeEvent) {
window.removeEventListener('hashchange', hashchangeEvent);
}
if (loadEvent) {
window.removeEventListener('load', loadEvent);
}
// check periodically if localStorage has customUrl available for 10 seconds
//if available call handleCustomUrlScheme and clear the interval and localStorage customUrl
var attempts = 5;
var customUrlInterval = setInterval(() => {
const customUrl = getCustomUrl();
if(customUrl && isValidUrl(customUrl)){
handleCustomUrlScheme(customUrl);
localStorage.removeItem("customUrl");
clearInterval(customUrlInterval);
}
if (attempts < 0) {
localStorage.removeItem("customUrl");
clearInterval(customUrlInterval);
}
attempts--;
}, 1000);
}
function initialize() {
hashchangeEvent = window.addEventListener('hashchange', function () {
handle();
});
loadEvent = window.addEventListener('load', (event) => {
handle();
});
}
return {
initialize: initialize,
isValidUrl: isValidUrl,
};
};
})(window, jQuery);

View File

@ -51,22 +51,22 @@
gearUtils.updateDefaultBuffers(selectedDeviceInfo, frameBuffers)
}
function onFramesizeChanged() {
async function onFramesizeChanged() {
//context.JK.prodBubble($resyncBtn, 'push-resync-when-done', {}, {positions:['top']});
updateDefaultBuffers();
context.jamClient.FTUESetFrameSize(frameBuffers.selectedFramesize());
await context.jamClient.FTUESetFrameSize(frameBuffers.selectedFramesize());
invalidateScore();
}
function onBufferInChanged() {
async function onBufferInChanged() {
//context.JK.prodBubble($resyncBtn, 'push-resync-when-done', {}, {positions:['top']});
context.jamClient.FTUESetInputLatency(frameBuffers.selectedBufferIn());
await context.jamClient.FTUESetInputLatency(frameBuffers.selectedBufferIn());
invalidateScore();
}
function onBufferOutChanged() {
async function onBufferOutChanged() {
//context.JK.prodBubble($resyncBtn, 'push-resync-when-done', {}, {positions:['top']});
context.jamClient.FTUESetOutputLatency(frameBuffers.selectedBufferOut());
await context.jamClient.FTUESetOutputLatency(frameBuffers.selectedBufferOut());
invalidateScore();
}
@ -110,12 +110,13 @@
}
}
function beforeShow() {
selectedDeviceInfo = gearUtils.selectedDeviceInfo(context.jamClient.FTUEGetInputMusicDevice(), context.jamClient.FTUEGetOutputMusicDevice());
deviceInformation = gearUtils.loadDeviceInfo();
startingFramesize = context.jamClient.FTUEGetFrameSize();
startingBufferIn = context.jamClient.FTUEGetInputLatency();
startingBufferOut = context.jamClient.FTUEGetOutputLatency();
async function beforeShow() {
let [p1, p2] = await Promise.all([context.jamClient.FTUEGetInputMusicDevice(), context.jamClient.FTUEGetOutputMusicDevice()])
selectedDeviceInfo = await gearUtils.selectedDeviceInfo(p1, p1);
deviceInformation = await gearUtils.loadDeviceInfo();
startingFramesize = await context.jamClient.FTUEGetFrameSize();
startingBufferIn = await context.jamClient.FTUEGetInputLatency();
startingBufferOut = await context.jamClient.FTUEGetOutputLatency();
var startingSpeed = translateFrameSizeToSpeed(startingFramesize)
logger.debug("speed upon entry: " + startingSpeed)
$speedOptions.filter('[value=' + startingSpeed + ']').iCheck('check')
@ -219,7 +220,7 @@
}
function initialize() {
async function initialize() {
var dialogBindings = {
'beforeShow': beforeShow,
'beforeHide': beforeHide,
@ -238,7 +239,7 @@
$fairLabel = $dialog.find('label[for="adjust-gear-speed-fair"]')
$fastLabel = $dialog.find('label[for="adjust-gear-speed-fast"]')
operatingSystem = context.JK.GetOSAsString();
operatingSystem = await context.JK.GetOSAsString();
$frameBuffers = $dialog.find('.frame-and-buffers');
frameBuffers.initialize($frameBuffers);

View File

@ -120,15 +120,17 @@
})
}
function onUsbDeviceConnected() {
if(!context.jamClient.IsFrontendVisible()) {return;} // don't handle USB events when minimized
async function onUsbDeviceConnected() {
var isFrontendVisible = await context.jamClient.IsFrontendVisible()
if(!isFrontendVisible) {return;} // don't handle USB events when minimized
logger.debug("USB device connected");
scheduleRescanSystem(3000);
}
function onUsbDeviceDisconnected() {
if(!context.jamClient.IsFrontendVisible()) {return;} // don't handle USB events when minimized
async function onUsbDeviceDisconnected() {
var isFrontendVisible = await context.jamClient.IsFrontendVisible()
if(!isFrontendVisible) {return;} // don't handle USB events when minimized
logger.debug("USB device disconnected");
scheduleRescanSystem(3000);
@ -149,8 +151,8 @@
context.JK.Banner.showYesNo({
title: "Confirm Restart",
html: "Are you sure you want to restart JamKazam?",
yes: function() {
context.jamClient.RestartApplication();
yes: async function() {
await context.jamClient.RestartApplication();
},
no : function() {
context.JK.Banner.hide();

View File

@ -50,31 +50,31 @@
context.JK.checkbox($autoStartInput);
context.JK.checkbox($useStaticPortInput);
$btnSave.click(function() {
$btnSave.click(async function() {
if (!validate()) {
return false;
}
var autostart = $autoStartField.find('.icheckbox_minimal').is('.checked');
context.jamClient.SetAutoStart(autostart);
await context.jamClient.SetAutoStart(autostart);
var useStaticPort = $useStaticPortField.find('.icheckbox_minimal').is('.checked');
context.jamClient.SetUseStaticPort(useStaticPort);
await context.jamClient.SetUseStaticPort(useStaticPort);
var staticPort = new Number($staticPortInput.val());
context.jamClient.SetStaticPort(staticPort);
await context.jamClient.SetStaticPort(staticPort);
app.layout.closeDialog('client-preferences-dialog')
context.jamClient.SaveSettings();
await context.jamClient.SaveSettings();
logger.debug("New Client Settings", {autostart: autostart, useStaticPort: useStaticPort, staticPort: staticPort})
if ((beforeValues.useStaticPort != useStaticPort) || (beforeValues.staticPort != staticPort)) {
context.JK.Banner.showYesNo({
title: "Please Restart",
html: "The changes you made won't take effect until you restart JamKazam. Restart now?",
yes: function() {
context.jamClient.RestartApplication();
yes: async function() {
await context.jamClient.RestartApplication();
},
no : function() {
context.JK.Banner.hide();
@ -85,14 +85,14 @@
})
}
function beforeShow() {
var autostart = context.jamClient.GetAutoStart();
async function beforeShow() {
var autostart = await context.jamClient.GetAutoStart();
autostart ? $autoStartInput.iCheck('check') : $autoStartInput.iCheck('uncheck');
var useStaticPort = context.jamClient.GetUseStaticPort();
var useStaticPort = await context.jamClient.GetUseStaticPort();
useStaticPort ? $useStaticPortInput.iCheck('check') : $useStaticPortInput.iCheck('uncheck');
var staticPort = context.jamClient.GetStaticPort();
var staticPort = await context.jamClient.GetStaticPort();
$staticPortInput.val(staticPort);

View File

@ -33,9 +33,9 @@
rest.getSessionHistory(sessionId)
.done(function(response) {
if (response && response.comments) {
$.each(response.comments, function(index, val) {
$.each(response.comments, async function(index, val) {
renderComment(val.comment, val.creator.id, val.creator.name,
context.JK.resolveAvatarUrl(val.creator.photo_url), $.timeago(val.created_at), val.creator.musician, true);
await context.JK.resolveAvatarUrl(val.creator.photo_url), $.timeago(val.created_at), val.creator.musician, true);
});
context.JK.bindHoverEvents($content);
context.JK.bindProfileClickEvents($content, ['comment-dialog']);
@ -49,9 +49,9 @@
rest.getClaimedRecording(claimedRecordingId)
.done(function(response) {
if (response.recording && response.recording.comments) {
$.each(response.recording.comments, function(index, val) {
$.each(response.recording.comments, async function(index, val) {
renderComment(val.comment, val.creator.id, val.creator.name,
context.JK.resolveAvatarUrl(val.creator.photo_url), $.timeago(val.created_at), val.creator.musician, true);
await context.JK.resolveAvatarUrl(val.creator.photo_url), $.timeago(val.created_at), val.creator.musician, true);
});
context.JK.bindHoverEvents($content);

View File

@ -158,7 +158,7 @@
//context.JK.dropdown($certifiedAudioProfile);
}
function deviceChanged() {
async function deviceChanged() {
var profile = $certifiedAudioProfile.val();
if(currentProfile == profile) {
@ -166,7 +166,7 @@
}
logger.debug("activating audio profile: " + profile);
var result = context.jamClient.FTUELoadAudioConfiguration(profile);
var result = await context.jamClient.FTUELoadAudioConfiguration(profile);
if(!result) {
logger.error("unable to activate audio configuration: " + profile + ", " + JSON.stringify(result));
@ -176,7 +176,7 @@
}
// FTUELoadAudioConfiguration eventually sets this, but apparently asynchronously
result = context.jamClient.SetLastUsedProfileName(profile);
result = await context.jamClient.SetLastUsedProfileName(profile);
if(!result) {
logger.error("unable to activate audio configuration after loading it: " + profile);
@ -189,20 +189,20 @@
window.ConfigureTracksActions.reset(false);
}
function beforeShow() {
async function beforeShow() {
profiles = gearUtils.getProfiles();
profiles = await gearUtils.getProfiles();
renderCertifiedGearDropdown();
showMusicAudioPanel();
currentProfile = context.jamClient.LastUsedProfileName();
currentProfile = await context.jamClient.LastUsedProfileName();
if(currentProfile != $certifiedAudioProfile.val()) {
logger.error("the currently active profile (" + currentProfile + ") is not the same as the Certified Audio Gear dropdown (" + $certifiedAudioProfile.val() + ")");
context.JK.alertSupportedNeeded("Unable to determine the current profile.");
}
var result = context.jamClient.FTUELoadAudioConfiguration(currentProfile);
var result = await context.jamClient.FTUELoadAudioConfiguration(currentProfile);
if(!result) {
logger.error("unable to activate audio configuration: " + currentProfile + ", " + JSON.stringify(result));
@ -221,12 +221,12 @@
voiceChatHelper.beforeShow();
}
function delayEnableVst() {
async function delayEnableVst() {
if (enableVstTimeout) {
clearTimeout(enableVstTimeout)
}
var isVstLoaded = context.jamClient.IsVstLoaded()
var hasVstAssignment = context.jamClient.hasVstAssignment()
var isVstLoaded = await context.jamClient.IsVstLoaded()
var hasVstAssignment = await context.jamClient.hasVstAssignment()
if (hasVstAssignment && !isVstLoaded) {
enableVstTimeout = setTimeout(function() { enableVst() }, 1000)

View File

@ -20,7 +20,7 @@
var template = $('#template-friend-selection').html();
var friends = rest.getFriends({ id: context.JK.currentUserId })
.done(function(friends) {
$.each(friends, function(index, val) {
$.each(friends, async function(index, val) {
var id = val.id;
var isSelected = selectedIds[id];
@ -28,7 +28,7 @@
userId: id,
css_class: isSelected ? 'selected' : '',
userName: val.name,
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
avatar_url: await context.JK.resolveAvatarUrl(val.photo_url),
status: "",
status_img_url: "",
check_mark_display: isSelected ? "block" : "none",

View File

@ -24,13 +24,13 @@
function registerEvents() {
$setupGearBtn.click(function() {
$setupGearBtn.click(async function() {
if (gon.isNativeClient) {
app.layout.closeDialog('getting-started');
// if no profiles, show FTUE in-line, if any, redirect to audio profile line
var profiles = context.jamClient.FTUEGetAllAudioConfigurations();
var profiles = await context.jamClient.FTUEGetAllAudioConfigurations();
if(profiles && profile.length > 0) {
window.location = '/client#/account/audio'

View File

@ -28,7 +28,8 @@
resetPagination();
showing = true;
getRecordings(0)
.done(function(data, textStatus, jqXHR) {
.then(function(resp) {
const [claimedRecordings, textStatus, jqXHR] = resp;
// initialize pagination
var $paginator = context.JK.Paginator.create(parseInt(jqXHR.getResponseHeader('total-entries')), perPage, 0, onPageSelected)
$('#local-recordings-dialog .paginator-holder').append($paginator);
@ -45,15 +46,15 @@
}
function getRecordings(page) {
return rest.getClaimedRecordings({page:page + 1, per_page:10})
.done(function(claimedRecordings) {
const promise = rest.getClaimedRecordingsPromise({page:page + 1, per_page:10})
promise.then(async function(resp) {
const [claimedRecordings, textStatus, jqXHR] = resp;
emptyList();
var $tbody = tbody();
const $tbody = tbody();
var recordings = $.map(claimedRecordings, function(val, i) { return val.recording; });
var localResults = context.jamClient.GetLocalRecordingState({recordings: recordings});
const recordings = $.map(claimedRecordings, function(val, i) { return val.recording; });
const localResults = await context.jamClient.GetLocalRecordingState({recordings: recordings});
if(localResults['error']) {
app.notify({
@ -69,7 +70,7 @@
$.each(claimedRecordings, function(index, claimedRecording) {
var options = {
const options = {
recordingId: claimedRecording.recording.id,
//date: context.JK.formatDate(claimedRecording.recording.created_at),
//time: context.JK.formatTime(claimedRecording.recording.created_at),
@ -79,15 +80,18 @@
duration: context.JK.prettyPrintSeconds(claimedRecording.recording.duration)
};
var tr = $(context._.template($('#template-claimed-recording-row').html(), options, { variable: 'data' }));
const tr = $(context._.template($('#template-claimed-recording-row').html(), options, { variable: 'data' }));
tr.data('server-model', claimedRecording);
$tbody.append(tr);
});
})
.fail(function(jqXHR, textStatus, errorMessage) {
.catch(function(error) {
const [jqXHR, textStatus, errorMessage] = error;
app.ajaxError(jqXHR, textStatus, errorMessage);
});
return promise;
}
function registerStaticEvents() {
@ -123,13 +127,13 @@
// tell the server we are about to start a recording
rest.startPlayClaimedRecording({id: context.SessionStore.id(), claimed_recording_id: claimedRecording.id})
.done(function(response) {
.then(async function(response) {
// update session info
context.SessionActions.updateSession.trigger(response);
var recordingId = $(this).attr('data-recording-id');
var openRecordingResult = context.jamClient.OpenRecording(claimedRecording.recording);
var openRecordingResult = await context.jamClient.OpenRecording(claimedRecording.recording);
logger.debug("OpenRecording response: %o", openRecordingResult);
@ -153,14 +157,15 @@
app.layout.closeDialog('localRecordings');
$(this).triggerHandler('openedSession', {});
}
openingRecording = false;
})
.fail(function(jqXHR) {
.catch(function(jqXHR) {
app.notifyServerError(jqXHR, "Unable to Open Recording For Playback");
})
.always(function() {
openingRecording = false;
openingRecording = false;
})
// .finally(function() {
// openingRecording = false;
// })
}

View File

@ -46,9 +46,9 @@
return getBackingTracks(targetPage);
}
function getBackingTracks(page) {
async function getBackingTracks(page) {
var result = context.jamClient.getBackingTrackList();
var result = await context.jamClient.getBackingTrackList();
var backingTracks = result.backing_tracks;
if (!backingTracks || backingTracks.length == 0) {
@ -86,8 +86,8 @@
// tell the server we are about to open a backing track:
rest.openBackingTrack({id: context.SessionStore.id(), backing_track_path: backingTrack.name})
.done(function(response) {
var result = context.jamClient.SessionOpenBackingTrackFile(backingTrack.name, false);
.done(async function(response) {
var result = await context.jamClient.SessionOpenBackingTrackFile(backingTrack.name, false);
// TODO: Possibly actually check the result. Investigate
// what real client returns:
@ -112,9 +112,9 @@
context.JK.helpBubble($whatAreBackingTracks, 'no help yet for this topic', {}, {positions:['bottom'], offsetParent: $dialog})
$whatAreBackingTracks.on('click', false) // no help yet
$displayAudioFileFolder.on('click', function(e) {
$displayAudioFileFolder.on('click', async function(e) {
e.stopPropagation();
context.jamClient.OpenBackingTracksDirectory();
await context.jamClient.OpenBackingTracksDirectory();
})
}

View File

@ -96,11 +96,11 @@
}
function afterShow() {
async function afterShow() {
$dialog.data('result', null)
showing = true;
sampleRate = context.jamClient.GetSampleRate()
sampleRate = await context.jamClient.GetSampleRate()
sampleRateForFilename = sampleRate == 48 ? '48' : '44';
doSearch();
}
@ -134,14 +134,14 @@
emptyList();
$.each(purchasedJamTracks.jamtracks, function(index, jamTrack) {
$.each(purchasedJamTracks.jamtracks, async function(index, jamTrack) {
var options = {}
options.jamTrackState = null;
options.jamTrackId = jamTrack.id;
options.name = jamTrack.name;
options.artist = jamTrack.original_artist;
var detail = context.jamClient.JamTrackGetTrackDetail(jamTrack.id + '-' + sampleRateForFilename) || {}
var detail = await context.jamClient.JamTrackGetTrackDetail(jamTrack.id + '-' + sampleRateForFilename) || {}
options.downloaded = detail.key_state == 'ready' ? 'Yes' : 'No'
var $tr = $(context._.template($templateOpenJamTrackRow.html(), options, { variable: 'data' }));

View File

@ -81,7 +81,7 @@
}
return false;
});
$('#btn-rate-session-send', $scopeSelector).click(function(evt) {
$('#btn-rate-session-send', $scopeSelector).click(async function(evt) {
var rr = getRating(), cc = getComment();
if (0 == rr && 0 == cc.length) {
closeDialog();
@ -93,10 +93,10 @@
}
var url = "/api/participant_histories/"+clientId+"/rating";
// get backend details too
if(context.jamClient.getAllClientsStateMap) {
var backendDetails = context.jamClient.getAllClientsStateMap()
//if(context.jamClient.getAllClientsStateMap) {
var backendDetails = await context.jamClient.getAllClientsStateMap()
console.log("got backend details", backendDetails)
}
//}
$.ajax({
type: "POST",

View File

@ -36,7 +36,7 @@
removeGoogleLoginErrors()
}
function beforeShow() {
async function beforeShow() {
$dialog.data('result', null);
if (recording == null) {
alert("recording data should not be null");
@ -46,7 +46,7 @@
resetForm();
if(context.jamClient.getClientParentChildRole() == CLIENT_ROLE.CHILD) {
if(await context.jamClient.getClientParentChildRole() == CLIENT_ROLE.CHILD) {
logger.debug("child client; launching preview after xfer");
$('#recording-finished-dialog span.nowait').addClass('hidden')
@ -61,14 +61,14 @@
$('#recording-finished-dialog span.nowait').removeClass('hidden')
$('#recording-finished-dialog .preview-area').css('visibility', 'visible')
$('#recording-finished-dialog form').css('visibility', 'visible')
launchPreview();
await launchPreview();
}
}
function waitForMixTransfer() {
timeout = setTimeout(function() {
timeout = setTimeout(async function() {
console.log("checking for file transfer", window.RecordingStore.mixTransferred)
if(window.RecordingStore.mixTransferred) {
@ -77,7 +77,7 @@
$('#recording-finished-dialog .preview-area').css('visibility', 'visible')
$('#recording-finished-dialog form').css('visibility', 'visible')
timeout = null
launchPreview()
await launchPreview()
}
else {
waitForMixTransfer();
@ -86,7 +86,7 @@
}, 1000)
}
function launchPreview() {
async function launchPreview() {
var parentSelector = '#recording-finished-dialog div.genre-selector';
context.JK.GenreSelectorHelper.render(parentSelector);
@ -97,7 +97,7 @@
context.JK.GenreSelectorHelper.setSelectedGenres(parentSelector, [genreDescription]);
}
var localResults = context.jamClient.GetLocalRecordingState({recordings: [recording]});
var localResults = await context.jamClient.GetLocalRecordingState({recordings: [recording]});
if (localResults['error']) {
logger.error("unable to open recording due to error: %o", localResults);
@ -128,7 +128,7 @@
else {
// load recording
var openRecordingResult = context.jamClient.PreviewRecording(recording);
var openRecordingResult = await context.jamClient.PreviewRecording(recording);
logger.debug("OpenRecording response: %o", openRecordingResult);
@ -161,7 +161,7 @@
}
}
}
function afterHide() {
async function afterHide() {
if(timeout) {
clearTimeout(timeout)
timeout = null
@ -177,12 +177,12 @@
logger.debug("VideoDecision rid:" + recording.id + ", name=" + name + ", keepResult=" + keepResult + ", saveToDisk=" + saveToDisk);
context.jamClient.VideoDecision(recording.id, name, keepResult && saveToDisk)
await context.jamClient.VideoDecision(recording.id, name, keepResult && saveToDisk)
}
recording = null;
playbackControls.stopMonitor();
context.jamClient.ClosePreviewRecording();
await context.jamClient.ClosePreviewRecording();
}
function onCancel() {
@ -337,24 +337,24 @@
}
}
function onPause() {
async function onPause() {
logger.debug("calling jamClient.SessionPausePlay");
context.jamClient.SessionPausePlay();
await context.jamClient.SessionPausePlay();
}
function onStop() {
async function onStop() {
logger.debug("calling jamClient.SessionStopPlay");
context.jamClient.SessionStopPlay();
await context.jamClient.SessionStopPlay();
}
function onPlay(e, data) {
async function onPlay(e, data) {
logger.debug("calling jamClient.SessionStartPlay");
context.jamClient.SessionStartPlay(data.playbackMode);
await context.jamClient.SessionStartPlay(data.playbackMode);
}
function onChangePlayPosition(e, data) {
async function onChangePlayPosition(e, data) {
logger.debug("calling jamClient.SessionTrackSeekMs(" + data.positionMs + ")");
context.jamClient.SessionTrackSeekMs(data.positionMs);
await context.jamClient.SessionTrackSeekMs(data.positionMs);
}
function registerStaticEvents() {

View File

@ -23,14 +23,23 @@ context.JK.SessionMasterMixDialog = class SessionMasterMixDialog
@app.bindDialog(@dialogId, dialogBindings)
@content = @dialog.find(".dialog-inner")
beforeShow:() =>
@logger.debug("session-master-mix-dlg: beforeShow")
context.jamClient.SetMixerMode(MIX_MODES.MASTER)
# beforeShow:() =>
# @logger.debug("session-master-mix-dlg: beforeShow")
# context.jamClient.SetMixerMode(MIX_MODES.MASTER)
beforeShow: `async function(){
this.logger.debug("session-master-mix-dlg: beforeShow");
await context.jamClient.SetMixerMode(MIX_MODES.MASTER);
}`
afterShow:() =>
@logger.debug("session-master-mix-dlg: afterShow")
afterHide:() =>
context.jamClient.SetMixerMode(MIX_MODES.PERSONAL)
# afterHide:() =>
# context.jamClient.SetMixerMode(MIX_MODES.PERSONAL)
afterHide: `async function(){
await context.jamClient.SetMixerMode(MIX_MODES.PERSONAL);
}`

View File

@ -15,9 +15,9 @@
var rest = new JK.Rest();
var sessionId;
function beforeShow(data) {
async function beforeShow(data) {
var canPlayWithOthers = gearUtils.canPlayWithOthers();
var canPlayWithOthers = await gearUtils.canPlayWithOthers();
context.JK.GenreSelectorHelper.render('#session-settings-genre');
$dialog = $('[layout-id="session-settings"]');

View File

@ -452,7 +452,7 @@
registerEvents(false);
}
function initialize(_facebookHelper) {
async function initialize(_facebookHelper) {
facebookHelper = _facebookHelper;
var dialogBindings = {
@ -467,9 +467,9 @@
facebookHelper.deferredLoginStatus().done(function(response) { handleFbStateChange(response); });
if(context.jamClient.IsNativeClient()) {
$("#btn-share-copy").unbind('click').click(function() {
context.jamClient.SaveToClipboard($("#link-contents").text());
if(context.JK.isQWebEngine) {
$("#btn-share-copy").unbind('click').click(async function() {
await context.jamClient.SaveToClipboard($("#link-contents").text());
return false;
})
}

View File

@ -15,20 +15,20 @@
logger.debug("'CANCEL SHUTDOWN' selected")
context.JK.Banner.hide();
}},
{name: 'SHUT DOWN', click: function() {
{name: 'SHUT DOWN', click: async function() {
logger.debug("'COMPLETELY SHUT DOWN THE APP' selected")
context.jamClient.ShutdownApplication()
await context.jamClient.ShutdownApplication()
}},
],
html: $('#template-shutdown-prompt').html()});
}
function initialize() {
async function initialize() {
// guard against old clients
if(context.jamClient.RegisterQuitCallback) {
context.jamClient.RegisterQuitCallback("window.JK.ShutdownDialogCallback");
}
//if(context.jamClient.RegisterQuitCallback) {
await context.jamClient.RegisterQuitCallback("window.JK.ShutdownDialogCallback");
//}
}
function quitCallback(options) {

View File

@ -30,7 +30,7 @@ context.JK.SoundCloudPlayerDialog = class SoundCloudPlayerDialog
@player.attr("src", "")
# the Windows client does not play back correctly
if context.jamClient.IsNativeClient()
if context.JK.isQWebEngine
context.JK.popExternalLink(@url)
return false
else

View File

@ -262,7 +262,7 @@
}
// called from sidebar when messages come in
function messageReceived(payload) {
async function messageReceived(payload) {
if(showing && otherId == payload.sender_id) {
if(fullyInitialized) {
renderMessage(payload.msg, payload.sender_id, payload.sender_name, payload.created_at, true);
@ -278,7 +278,7 @@
app.notify({
"title": "Message from " + payload.sender_name,
"text": payload.msg,
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
"icon_url": await context.JK.resolveAvatarUrl(payload.photo_url)
}, [{
id: "btn-reply",
text: "REPLY",

View File

@ -9,9 +9,10 @@
var rest = context.JK.Rest();
var dialogId = '#video-dialog';
function videoClick(e) {
async function videoClick(e) {
var $self = $(this);
if (!context.jamClient || !context.jamClient.IsNativeClient()) {
var isNativeClient = context.JK.isQWebEngine;
if (!isNativeClient) {
$('#video-dialog-header').html($self.data('video-header') || $self.attr('data-video-header'));
$('#video-dialog-iframe').attr('src', $self.data('video-url') || $self.attr('data-video-url'));
@ -22,7 +23,7 @@
}
else {
var videoUrl = $.param.querystring(window.location.href, 'showVideo=' + encodeURIComponent($self.data('video-url')));
context.jamClient.OpenSystemBrowser(videoUrl);
await context.jamClient.OpenSystemBrowser(videoUrl);
}
}

View File

@ -148,7 +148,8 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
@stateHolder.children().remove()
@stateHolder.append(context._.template(@state.template.html(), @jamTrack, { variable: 'data' }))
@stateHolder.find('.' + @size).removeClass('hidden')
@state.show()
# force this
@state.show.call(this)
# report a stat now that we've reached the end of this widget's journey
trackProgress: () =>
@ -184,38 +185,65 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
@tracked = true
showPackaging: () =>
@logger.debug("showing #{@state.name}")
console.log("showing #{@state.name}")
this.expectTransition()
showDownloading: () =>
@logger.debug("showing #{@state.name}")
# while downloading, we don't run the transition timer, because the download API is guaranteed to call success, or failure, eventually
context.jamClient.JamTrackDownload(@jamTrack.id, null, context.JK.currentUserId,
# showDownloading: () =>
# console.log("showing #{@state.name}")
# # while downloading, we don't run the transition timer, because the download API is guaranteed to call success, or failure, eventually
# context.jamClient.JamTrackDownload(@jamTrack.id, null, context.JK.currentUserId,
# this.makeDownloadProgressCallback(),
# this.makeDownloadSuccessCallback(),
# this.makeDownloadFailureCallback())
showDownloading: `async function(){
console.log('showing '+this.state.name);
// while downloading, we do not run the transition timer, because the download API is guaranteed to call success, or failure, eventually
await context.jamClient.JamTrackDownload(this.jamTrack.id, null, context.JK.currentUserId,
this.makeDownloadProgressCallback(),
this.makeDownloadSuccessCallback(),
this.makeDownloadFailureCallback())
this.makeDownloadFailureCallback());
}`
showKeying: () =>
@logger.debug("showing #{@state.name}")
context.jamClient.JamTrackKeysRequest()
this.waitForState()
# showKeying: () =>
# console.log("showing #{@state.name}")
# context.jamClient.JamTrackKeysRequest()
# this.waitForState()
showKeying: `async function(){
this.logger.debug('showing '+this.state.name);
await context.jamClient.JamTrackKeysRequest();
this.waitForState();
}`
showQuiet: () =>
@logger.debug("showing #{@state.name}")
console.log("showing #{@state.name}")
showInitial: () =>
@logger.debug("showing #{@state.name}")
@sampleRate = context.jamClient.GetSampleRate()
@fingerprint = context.jamClient.SessionGetMacHash()
logger.debug("fingerprint: ", @fingerprint)
@sampleRateForFilename = if @sampleRate == 48 then '48' else '44'
@attempts = @attempts + 1
this.expectTransition()
context.JK.SubscriptionUtils.subscribe('jam_track_right', @jamTrack.jam_track_right_id).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, this.onJamTrackRightEvent)
this.checkState()
# showInitial: () =>
# console.log("showing #{@state.name}")
# @sampleRate = context.jamClient.GetSampleRate()
# @fingerprint = context.jamClient.SessionGetMacHash()
# logger.debug("fingerprint: ", @fingerprint)
# @sampleRateForFilename = if @sampleRate == 48 then '48' else '44'
# @attempts = @attempts + 1
# this.expectTransition()
# context.JK.SubscriptionUtils.subscribe('jam_track_right', @jamTrack.jam_track_right_id).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, this.onJamTrackRightEvent)
# this.checkState()
showInitial: `async function() {
console.log('showing '+ this.state.name);
this.sampleRate = await context.jamClient.GetSampleRate();
this.fingerprint = await context.jamClient.SessionGetMacHash();
console.log("fingerprint: ", this.fingerprint);
this.sampleRateForFilename = this.sampleRate === 48 ? '48' : '44';
this.attempts = this.attempts + 1;
this.expectTransition();
context.JK.SubscriptionUtils.subscribe('jam_track_right', this.jamTrack.jam_track_right_id).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, this.onJamTrackRightEvent);
this.checkState();
}`
showError: () =>
@logger.debug("showing #{@state.name}")
console.log("showing #{@state.name}")
context.JK.SubscriptionUtils.unsubscribe('jam_track_right', @jamTrack.jam_track_right_id)
if @size == 'large'
@ -233,17 +261,17 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
@stateHolder.find('.retry').text(retryMsg)
showSynchronized: () =>
@logger.debug("showing #{@state.name}")
console.log("showing #{@state.name}")
context.JK.SubscriptionUtils.unsubscribe('jam_track_right', @jamTrack.jam_track_right_id)
showNoClient: () =>
@logger.debug("showing #{@state.name}")
console.log("showing #{@state.name}")
downloadCheck: () =>
@logger.debug "downloadCheck"
console.log "downloadCheck"
retry: () =>
@logger.debug "user initiated retry"
console.log "user initiated retry"
@path = []
@path.push('retry')
this.clear()
@ -263,7 +291,7 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
# if not, then let's see if we have timed out
if @state.timer?
if (new Date()).getTime() - @state.stateStartTime.getTime() > @state.max_time
@logger.debug("The current step (#{@state.name}) took too long")
console.log("The current step (#{@state.name}) took too long")
if @state == @states.keying
# specific message
@ -327,19 +355,19 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
return
if newState == @state
@logger.debug("DownloadJamTrack: ignoring state change #{@state.name}")
console.log("DownloadJamTrack: ignoring state change #{@state.name}")
return
if @state?
@logger.debug("DownloadJamTrack: state change: #{@state.name} => #{newState.name}")
console.log("DownloadJamTrack: state change: #{@state.name} => #{newState.name}")
# make sure there is no timer running on the old state
this.clearTransitionTimer()
this.clearStateTimer()
this.abortEnqueue()
@logger.debug("aborting getJamTrack right on state change")
console.log("aborting getJamTrack right on state change")
this.abortGetJamTrackRight()
else
@logger.debug("DownloadJamTrack: initial state: #{newState.name}")
console.log("DownloadJamTrack: initial state: #{newState.name}")
@state = newState
@ -353,38 +381,76 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
$(this).triggerHandler(@EVENTS.JAMTRACK_DOWNLOADER_STATE_CHANGED, {state: @state})
checkState: () =>
# check for the success state against the local state of the client... if it's playable, then we should be OK
fqId = "#{@jamTrack.id}-#{@sampleRateForFilename}"
@trackDetail = context.jamClient.JamTrackGetTrackDetail (fqId)
# checkState: () =>
# # check for the success state against the local state of the client... if it's playable, then we should be OK
# fqId = "#{@jamTrack.id}-#{@sampleRateForFilename}"
# @trackDetail = context.jamClient.JamTrackGetTrackDetail (fqId)
@logger.debug("DownloadJamTrack: JamTrackGetTrackDetail(#{fqId}).key_state: " + @trackDetail.key_state, @trackDetail)
# console.log("DownloadJamTrack: JamTrackGetTrackDetail(#{fqId}).key_state: " + @trackDetail.key_state, @trackDetail)
# first check if the version is not the same; if so, invalidate.
# # first check if the version is not the same; if so, invalidate.
if @trackDetail.version?
if @jamTrack.version != @trackDetail.version
@logger.info("DownloadJamTrack: JamTrack on disk is different version (stored: #{@trackDetail.version}, server: #{@jamTrack.version}. Invalidating")
context.jamClient.InvalidateJamTrack("#{@jamTrack.id}-#{@sampleRateForFilename}")
@trackDetail = context.jamClient.JamTrackGetTrackDetail ("#{@jamTrack.id}-#{@sampleRateForFilename}")
# if @trackDetail.version?
# if @jamTrack.version != @trackDetail.version
# @logger.info("DownloadJamTrack: JamTrack on disk is different version (stored: #{@trackDetail.version}, server: #{@jamTrack.version}. Invalidating")
# context.jamClient.InvalidateJamTrack("#{@jamTrack.id}-#{@sampleRateForFilename}")
# @trackDetail = context.jamClient.JamTrackGetTrackDetail ("#{@jamTrack.id}-#{@sampleRateForFilename}")
if @trackDetail.version?
@logger.error("after invalidating package, the version is still wrong!", @trackDetail)
throw "after invalidating package, the version is still wrong! #{@trackDetail.version}"
# if @trackDetail.version?
# @logger.error("after invalidating package, the version is still wrong!", @trackDetail)
# throw "after invalidating package, the version is still wrong! #{@trackDetail.version}"
switch @trackDetail.key_state
when 'pending'
this.transition(@states.keying)
when 'not authorized'
# TODO: if not authorized, do we need to re-initiate a keying attempt?
this.transition(@states.keying)
when 'ready'
this.transition(@states.synchronized)
when 'unknown'
@ajaxGetJamTrackRightAborted = false
@rest.getJamTrackRight({id: @jamTrack.id})
# switch @trackDetail.key_state
# when 'pending'
# this.transition(@states.keying)
# when 'not authorized'
# # TODO: if not authorized, do we need to re-initiate a keying attempt?
# this.transition(@states.keying)
# when 'ready'
# this.transition(@states.synchronized)
# when 'unknown'
# @ajaxGetJamTrackRightAborted = false
# @rest.getJamTrackRight({id: @jamTrack.id})
# .done(this.processJamTrackRight)
# .fail(this.processJamTrackRightFail)
checkState: `async function() {
// check for the success state against the local state of the client... if its playable, then we should be OK
const fqId = this.jamTrack.id+'-'+this.sampleRateForFilename;
this.trackDetail = await context.jamClient.JamTrackGetTrackDetail((fqId));
this.logger.debug('DownloadJamTrack: JamTrackGetTrackDetail('+fqId+').key_state: ' + this.trackDetail.key_state, this.trackDetail);
//first check if the version is not the same; if so, invalidate.
if (this.trackDetail.version != null) {
if (this.jamTrack.version !== this.trackDetail.version) {
this.logger.info('DownloadJamTrack: JamTrack on disk is different version (stored: '+this.trackDetail.version+', server: '+this.jamTrack.version+'. Invalidating');
await context.jamClient.InvalidateJamTrack(this.jamTrack.id+'-'+this.sampleRateForFilename);
this.trackDetail = await context.jamClient.JamTrackGetTrackDetail((this.jamTrack.id+'-'+this.sampleRateForFilename));
if (this.trackDetail.version != null) {
this.logger.error("after invalidating package, the version is still wrong!", this.trackDetail);
throw 'after invalidating package, the version is still wrong! ' + this.trackDetail.version;
}
}
}
switch (this.trackDetail.key_state) {
case 'pending':
return this.transition(this.states.keying);
case 'not authorized':
// TODO: if not authorized, do we need to re-initiate a keying attempt?
return this.transition(this.states.keying);
case 'ready':
return this.transition(this.states.synchronized);
case 'unknown':
this.ajaxGetJamTrackRightAborted = false;
return this.rest.getJamTrackRight({id: this.jamTrack.id})
.done(this.processJamTrackRight)
.fail(this.processJamTrackRightFail)
.fail(this.processJamTrackRightFail);
}
}`
# update progress indicator for packaging step
updateSteps: () =>
@ -402,7 +468,7 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
@updateSteps()
@logger.debug("DownloadJamTrack: processSigningState: " + signingState)
console.log("DownloadJamTrack: processSigningState: " + signingState)
switch signingState
when 'QUIET'
@ -459,23 +525,23 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
processJamTrackRight: (myJamTrack) =>
@logger.debug("processJamTrackRight", myJamTrack)
console.log("processJamTrackRight", myJamTrack)
unless @ajaxGetJamTrackRightAborted
this.processSigningState(myJamTrack)
else
@logger.debug("DownloadJamTrack: ignoring processJamTrackRight response")
console.log("DownloadJamTrack: ignoring processJamTrackRight response")
processJamTrackRightFail: () =>
unless @ajaxGetJamTrackRightAborted?
this.transitionError("status-check-error", "Unable to check with the server on the status of your JamTrack.")
else
@logger.debug("DownloadJamTrack: ignoring processJamTrackRightFail response")
console.log("DownloadJamTrack: ignoring processJamTrackRightFail response")
processEnqueueJamTrack: (enqueueResponse) =>
unless @ajaxEnqueueAborted
this.expectTransition() # the act of enqueuing should send down events to the client. we wait...
else
@logger.debug("DownloadJamTrack: ignoring processEnqueueJamTrack response")
console.log("DownloadJamTrack: ignoring processEnqueueJamTrack response")
displayUIForGuard:(response) =>
display = switch response.message
@ -496,10 +562,10 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
else
this.transitionError("enqueue-error", "Unable to ask the server to build your JamTrack.")
else
@logger.debug("DownloadJamTrack: ignoring processEnqueueJamTrackFail response")
console.log("DownloadJamTrack: ignoring processEnqueueJamTrackFail response")
onJamTrackRightEvent: (e, data) =>
@logger.debug("DownloadJamTrack: subscription notification received: type:" + data.type, data)
console.log("DownloadJamTrack: subscription notification received: type:" + data.type, data)
this.expectTransition()
this.processSigningState(data.body)
@ -513,7 +579,7 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
@root.find('.state-downloading .progress').text(progress)
downloadProgressCallback: (bytesReceived, bytesTotal) =>
@logger.debug("download #{bytesReceived}/#{bytesTotal}")
console.log("download #{bytesReceived}/#{bytesTotal}")
@bytesReceived = Number(bytesReceived)
@bytesTotal = Number(bytesTotal)
@ -524,7 +590,7 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
downloadSuccessCallback: (updateLocation) =>
# is the package loadable yet?
@logger.debug("DownloadJamTrack: download complete - on to keying")
console.log("DownloadJamTrack: download complete - on to keying")
this.transition(@states.keying)
downloadFailureCallback: (errorMsg) =>

View File

@ -2,8 +2,11 @@
// !!!! Keep white space after last require !!!!
//
//= require fakeJamClient
//= require fakeJamClientProxy
//= require fakeJamClientMessages
//= require fakeJamClientRecordings
//= require qwebchannel.js
//= require asyncJamClient
//= require backend_alerts
//= require stun
//= require influxdb-latest
@ -28,12 +31,11 @@
$(window).on('pagehide', setNavigationStart)
}
$(document).on('JAMKAZAM_CONSTRUCTED', function(e, data) {
console.log('JAMKAZAM_CONSTRUCTED event called');
var app = data.app;
if(!app) throw "app not found";
// makes window.jamClient / context.jamClient set to something non-null very early on
context.JK.initJamClient(app);
@ -52,7 +54,8 @@
$.cookie("browser.timezone", window.jstz.determine().name(), { expires: 365, path: '/' });
}
$(document).on('JAMKAZAM_READY', function() {
$(document).on('JAMKAZAM_READY', async function() {
console.log('JAMKAZAM_READY event called');
// this event is fired when context.app is initialized
var app = context.JK.app;
@ -61,9 +64,9 @@
initializeDialogs(app);
checkAudioStopped();
await checkAudioStopped();
checkMacOSXInstalledCorrectly();
await checkMacOSXInstalledCorrectly();
watchPreferencesEvent(app);
@ -90,13 +93,14 @@
});
}
function checkMacOSXInstalledCorrectly() {
var os = context.jamClient.GetOSAsString();
async function checkMacOSXInstalledCorrectly() {
var os = await context.jamClient.GetOSAsString();
// check if method exists at all for migration purposes
if(context.jamClient.IsAppInWritableVolume && os == "MacOSX" && !context.jamClient.IsAppInWritableVolume()) {
var isAppInWritableVolume = await context.jamClient.IsAppInWritableVolume()
if(os == "MacOSX" && !isAppInWritableVolume) {
context.JK.Banner.showAlert(
{ title: "Drag JamKazam to the Applications Folder!",
buttons: [{name: 'SHUTDOWN APPLICATION', click: function() {context.jamClient.ShutdownApplication()}} ],
buttons: [{name: 'SHUTDOWN APPLICATION', click: async function() { await context.jamClient.ShutdownApplication()}} ],
html: $('#template-app-in-read-only-volume').html()});
return;
}
@ -164,36 +168,36 @@
}
// wait 10 seconds
function checkAudioStopped() {
async function checkAudioStopped() {
if(context.jamClient.ResetPageCounters) {
//if(context.jamClient.ResetPageCounters) {
// upgrade concern
context.jamClient.ResetPageCounters();
await context.jamClient.ResetPageCounters();
context.JK.AudioStopTimeout = setTimeout(function() {
context.JK.AudioStopTimeout = setTimeout(async function() {
if(context.jamClient.IsAudioStarted()) {
if(await context.jamClient.IsAudioStarted()) {
logger.debug("checkAudioStopped: stopping audio ...")
context.jamClient.StopAudio();
await context.jamClient.StopAudio();
}
}, 10000);
}
//}
}
function updateScoringIntervals() {
if(context.jamClient.SetLatencyTestBlocked) {
async function updateScoringIntervals() {
if(await context.jamClient.SetLatencyTestBlocked) {
// make sure latency testing is still going on, in case a refresh occurred during network test
context.jamClient.SetLatencyTestBlocked(false)
await context.jamClient.SetLatencyTestBlocked(false)
}
// set scoring intervals
if(context.jamClient.SetScoreWorkTimingInterval){
var success = context.jamClient.SetScoreWorkTimingInterval(
if(await context.jamClient.SetScoreWorkTimingInterval){
var success = await context.jamClient.SetScoreWorkTimingInterval(
{
interval: gon.global.scoring_get_work_interval,
backoff: gon.global.scoring_get_work_backoff_interval
})
if(!success) logger.warning("unable to set scoring intervals")
//if(!success) logger.warning("unable to set scoring intervals")
}
}
@ -213,6 +217,7 @@
}
function initializeStun(app) {
stun = new context.JK.Stun(app);
context.JK.StunInstance = stun;
stun.initialize();
@ -226,12 +231,12 @@
window.location.reload();
});
JK.JamServer.registerMessageCallback(JK.MessageType.RESTART_APPLICATION, function(header, payload) {
context.jamClient.RestartApplication();
JK.JamServer.registerMessageCallback(JK.MessageType.RESTART_APPLICATION, async function(header, payload) {
await context.jamClient.RestartApplication();
});
JK.JamServer.registerMessageCallback(JK.MessageType.STOP_APPLICATION, function(header, payload) {
context.jamClient.ShutdownApplication();
JK.JamServer.registerMessageCallback(JK.MessageType.STOP_APPLICATION, async function(header, payload) {
await context.jamClient.ShutdownApplication();
});
}

View File

@ -529,6 +529,10 @@
dbg('LeaveSession:' + JSON.stringify(map));
}
function LaunchBroadcastSettings() {
dbg('LaunchBroadcastSettings');
}
// this is not a real bridge method; purely used by the fake jam client
function RegisterP2PMessageCallbacks(callbacks) {
p2pCallbacks = callbacks;
@ -923,6 +927,7 @@
}
function SessionSetAlertCallback(callback) {
//console('running.....')
alertCallbackName = callback;
// simulate a backend alert
@ -1529,6 +1534,12 @@
return {}
}
function RegisterSessionJoinLeaveRequestCallBack(){}
function RegisterGenericCallBack(){}
function GetDetailedOS(){}
// Javascript Bridge seems to camel-case
// Set the instance functions:
this.AbortRecording = AbortRecording;
@ -1540,6 +1551,7 @@
this.JoinSession = JoinSession;
this.LatencyUpdated = LatencyUpdated;
this.LeaveSession = LeaveSession;
this.LaunchBroadcastSettings = LaunchBroadcastSettings;
this.P2PMessageReceived = P2PMessageReceived;
this.ParticipantJoined = ParticipantJoined;
this.ParticipantLeft = ParticipantLeft;
@ -1575,6 +1587,8 @@
this.GetStaticPort = GetStaticPort;
this.SetStaticPort = SetStaticPort;
this.connected = true;
this.RegisterGenericCallBack = RegisterGenericCallBack;
this.GetDetailedOS = GetDetailedOS;
// FTUE (round 3)
this.FTUESetInputMusicDevice = FTUESetInputMusicDevice;
@ -1664,6 +1678,7 @@
this.SessionPageEnter = SessionPageEnter;
this.SessionPageLeave = SessionPageLeave;
this.SetMixerMode = SetMixerMode;
this.RegisterSessionJoinLeaveRequestCallBack = RegisterSessionJoinLeaveRequestCallBack;
this.SetVURefreshRate = SetVURefreshRate;
this.SessionGetMasterLocalMix = SessionGetMasterLocalMix;
@ -1811,6 +1826,8 @@
this.listTrackAssignments = listTrackAssignments;
this.applySubscriptionPolicy = applySubscriptionPolicy;
this.clientID = "devtester";
this.NetworkTestResult = NetworkTestResult;
};
})(window, jQuery);

View File

@ -0,0 +1,35 @@
(function(context,$) {
"use strict";
context.JK = context.JK || {};
context.JK.FakeJamClientProxy = function(app, p2pMessageFactory) {
const handler = {
get: (target, prop, receiver) => {
return function (...args) {
return new Promise((resolve, reject) => {
try {
//console.log('[fakeJamClient]', prop)
if(target[prop]){
const result = target[prop].apply(target, args);
resolve(result);
}else{
console.error('[fakeJamClient] error: No such method in FakeJamClient', prop);
reject(`No such method in FakeJamClient: ${prop}`);
}
} catch (error) {
console.error('[fakeJamClient] error:', prop, error);
reject(error);
}
});
}
}
}
const fakeJamClient = new JK.FakeJamClient(app, p2pMessageFactory);
return new Proxy(fakeJamClient, handler);
}
})(window, jQuery);

View File

@ -46,19 +46,19 @@
'ftue-audio-output-fader': jamClient.FTUEGetOutputVolume
};
function latencyTimeoutCheck() {
async function latencyTimeoutCheck() {
if (context.JK.FtueWizard.latencyTimeout) {
jamClient.FTUERegisterLatencyCallback('');
await jamClient.FTUERegisterLatencyCallback('');
context.JK.app.setWizardStep("5");
}
}
function afterHide(data) {
async function afterHide(data) {
// Unsubscribe from FTUE VU callbacks.
jamClient.FTUERegisterVUCallbacks('', '', '');
await jamClient.FTUERegisterVUCallbacks('', '', '');
if (!successfulFtue && app.cancelFtue) {
app.cancelFtue();
await app.cancelFtue();
app.afterFtue = null;
app.cancelFtue = null;
}
@ -150,12 +150,12 @@
}
function settingsInit() {
jamClient.FTUEInit();
async function settingsInit() {
await jamClient.FTUEInit();
//setLevels(0);
resetFtueLatencyView();
setSaveButtonState($('#btn-ftue-2-save'), false);
if (jamClient.GetOSAsString() !== "Win32") {
if (await jamClient.GetOSAsString() !== "Win32") {
$('#btn-ftue-2-asio-control-panel').hide();
}
renderDisableTest();
@ -176,18 +176,19 @@
$('[layout-wizard="ftue"] [layout-wizard-step="2"] .settings-controls select[data-device="voice-chat-output"]').val("");
}
function setLevels(db) {
async function setLevels(db) {
if (db < -80 || db > 20) {
throw ("BUG! ftue.js:setLevels db arg must be between -80 and 20");
}
var trackIds = jamClient.SessionGetIDs();
var controlStates = jamClient.SessionGetControlState(trackIds);
$.each(controlStates, function (index, value) {
var trackIds = await jamClient.SessionGetIDs();
var controlStates = await jamClient.SessionGetControlState(trackIds);
$.each(controlStates, async function (index, value) {
context.JK.Mixer.fillTrackVolume(value, false);
// Default input/output to 0 DB
context.trackVolumeObject.volL = db;
context.trackVolumeObject.volR = db;
jamClient.SessionSetControlState(trackIds[index]);
//await jamClient.SessionSetControlState(trackIds[index]);
await context.jamClient.SessionSetTrackVolumeData(trackIds[index], null, context.trackVolumeObject)
});
$.each(context._.keys(faderMap), function (index, faderId) {
// faderChange takes a value from 0-100
@ -199,14 +200,14 @@
});
}
function testComplete() {
async function testComplete() {
logger.debug("Test complete");
var latencyMS = context.JK.FtueWizard.latencyMS;
var ftueSucceeded = latencyMS <= 20;
if (ftueSucceeded) {
logger.debug(latencyMS + " is <= 20. Setting FTUE status to true");
ftueSave(true); // Save the profile
context.jamClient.FTUESetStatus(true); // No FTUE wizard next time
await context.jamClient.FTUESetStatus(true); // No FTUE wizard next time
rest.userCertifiedGear({success: true});
// notify anyone curious about how it went
@ -300,36 +301,36 @@
}
function testLatency() {
async function testLatency() {
// we'll just register for call back right here and unregister in the callback.
context.JK.FtueWizard.latencyTimeout = true;
var cbFunc = 'JK.ftueLatencyCallback';
logger.debug("Registering latency callback: " + cbFunc);
jamClient.FTUERegisterLatencyCallback('JK.ftueLatencyCallback');
await jamClient.FTUERegisterLatencyCallback('JK.ftueLatencyCallback');
var now = new Date();
logger.debug("Starting Latency Test..." + now);
context.setTimeout(latencyTimeoutCheck, 300 * 1000); // Timeout to 5 minutes
jamClient.FTUEStartLatency();
await jamClient.FTUEStartLatency();
}
function openASIOControlPanel(evt) {
async function openASIOControlPanel(evt) {
if (win32) {
logger.debug("Calling FTUEOpenControlPanel()");
jamClient.FTUEOpenControlPanel();
await jamClient.FTUEOpenControlPanel();
}
}
function asioResync(evt) {
jamClient.FTUERefreshDevices();
async function asioResync(evt) {
await jamClient.FTUERefreshDevices();
ftueSave(false);
}
function ftueSave(persist) {
async function ftueSave(persist) {
// Explicitly set inputs and outputs to dropdown values
// before save as the client seems to want this on changes to
// things like frame size, etc..
var $audioSelects = $('[layout-wizard-step="2"] .settings-controls select');
$.each($audioSelects, function (index, value) {
$.each($audioSelects, async function (index, value) {
var $select = $(value);
setAudioDevice($select);
});
@ -341,16 +342,16 @@
// that we're using music for voice-chat.
if ($('[layout-wizard-step="2"] select[data-device="voice-chat-input"]').val()) {
// Voice input selected
jamClient.TrackSetChatEnable(true);
await jamClient.TrackSetChatEnable(true);
} else {
// No voice input selected.
jamClient.TrackSetChatEnable(false);
await jamClient.TrackSetChatEnable(false);
}
setDefaultInstrumentFromProfile();
logger.debug("Calling FTUESave(" + persist + ")");
var response = jamClient.FTUESave(persist);
var response = await jamClient.FTUESave(persist);
//setLevels(0);
if (response) {
logger.warn(response);
@ -363,33 +364,33 @@
}
}
function setAsioFrameSize(evt) {
async function setAsioFrameSize(evt) {
var val = parseFloat($(evt.currentTarget).val(), 10);
if (isNaN(val)) {
return;
}
logger.debug("Calling FTUESetFrameSize(" + val + ")");
jamClient.FTUESetFrameSize(val);
await jamClient.FTUESetFrameSize(val);
ftueSave(false);
}
function setAsioInputLatency(evt) {
async function setAsioInputLatency(evt) {
var val = parseInt($(evt.currentTarget).val(), 10);
if (isNaN(val)) {
return;
}
logger.debug("Calling FTUESetInputLatency(" + val + ")");
jamClient.FTUESetInputLatency(val);
await jamClient.FTUESetInputLatency(val);
ftueSave(false);
}
function setAsioOutputLatency(evt) {
async function setAsioOutputLatency(evt) {
var val = parseInt($(evt.currentTarget).val(), 10);
if (isNaN(val)) {
return;
}
logger.debug("Calling FTUESetOutputLatency(" + val + ")");
jamClient.FTUESetOutputLatency(val);
await jamClient.FTUESetOutputLatency(val);
ftueSave(false);
}
@ -402,8 +403,8 @@
return false;
}
function videoLinkClicked(evt) {
var myOS = jamClient.GetOSAsString();
async function videoLinkClicked(evt) {
var myOS = await jamClient.GetOSAsString();
var link;
if (myOS === 'MacOSX') {
link = $(evt.currentTarget).attr('external-link-mac');
@ -411,7 +412,7 @@
link = $(evt.currentTarget).attr('external-link-win');
}
if (link) {
context.jamClient.OpenSystemBrowser(link);
await context.jamClient.OpenSystemBrowser(link);
}
}
@ -449,7 +450,7 @@
* This function loads the available audio devices from jamClient, and
* builds up the select dropdowns in the audio-settings step of the FTUE wizard.
*/
function loadAudioDevices() {
async function loadAudioDevices() {
var funcs = [
jamClient.FTUEGetMusicInputs,
jamClient.FTUEGetChatInputs,
@ -461,13 +462,13 @@
'[layout-wizard-step="2"] .audio-output select'
];
var optionsHtml = '';
var deviceOptionFunc = function (deviceKey, index, list) {
var deviceOptionFunc = async function (deviceKey, index, list) {
optionsHtml += '<option title="' + devices[deviceKey] + '" value="' + deviceKey + '">' + devices[deviceKey] + '</option>';
};
for (var i = 0; i < funcs.length; i++) {
optionsHtml = '<option selected="selected" value="">Choose...</option>';
var devices = funcs[i](); // returns hash of device id: device name
var devices = await funcs[i](); // returns hash of device id: device name
var $select = $(selectors[i]);
$select.empty();
var sortedDeviceKeys = context._.keys(devices).sort();
@ -481,8 +482,8 @@
$('#asio-input-latency').val('0').change();
$('#asio-output-latency').val('0').change();
// Special-case for a non-ASIO device, set to 1
if (jamClient.GetOSAsString() === "Win32") { // Limit this check to Windows only.
if (!(jamClient.FTUEHasControlPanel())) {
if (await jamClient.GetOSAsString() === "Win32") { // Limit this check to Windows only.
if (!(await jamClient.FTUEHasControlPanel())) {
$('#asio-input-latency').val('1').change();
$('#asio-output-latency').val('1').change();
}
@ -493,9 +494,9 @@
/**
* Load available drivers and populate the driver select box.
*/
function loadAudioDrivers() {
var drivers = context.jamClient.FTUEGetDevices(false);
var chatDrivers = jamClient.FTUEGetChatInputs(false, false);
async function loadAudioDrivers() {
var drivers = await context.jamClient.FTUEGetDevices(false);
var chatDrivers = await jamClient.FTUEGetChatInputs(false, false);
var optionsHtml = '<option selected="selected" value="">Choose...</option>';
var chatOptionsHtml = '<option selected="selected" value="">Choose...</option>';
@ -558,7 +559,7 @@
/**
* Handler for the new FTUE save button.
*/
function newFtueSaveSettingsHandler(evt) {
async function newFtueSaveSettingsHandler(evt) {
evt.preventDefault();
var $saveButton = $('#btn-ftue-2-save');
if ($saveButton.hasClass('disabled')) {
@ -576,8 +577,8 @@
setDefaultInstrumentFromProfile();
logger.debug("Calling FTUESave(" + true + ")");
jamClient.FTUESave(true);
jamClient.FTUESetStatus(true); // No FTUE wizard next time
await jamClient.FTUESave(true);
await jamClient.FTUESetStatus(true); // No FTUE wizard next time
rest.userCertifiedGear({success: true});
// notify anyone curious about how it went
$('div[layout-id=ftue]').trigger('ftue_success');
@ -585,7 +586,7 @@
app.layout.closeDialog('ftue');
if (app.afterFtue) {
// If there's a function to invoke, invoke it.
app.afterFtue();
await app.afterFtue();
app.afterFtue = null;
app.cancelFtue = null;
}
@ -607,7 +608,7 @@
// { latency: 11.1875, latencyknown: true, latencyvar: 1}
function newFtueAudioDeviceChanged(evt) {
releaseDropdown(function () {
releaseDropdown(async function () {
renderStartNewFtueLatencyTesting();
var $select = $(evt.currentTarget);
@ -615,12 +616,12 @@
var $voiceSelect = $('.ftue-new .settings-2-voice select');
var audioDriverId = $audioSelect.val();
var voiceDriverId = $voiceSelect.val();
jamClient.FTUESetMusicDevice(audioDriverId);
jamClient.FTUESetChatInput(voiceDriverId);
await jamClient.FTUESetMusicDevice(audioDriverId);
await jamClient.FTUESetChatInput(voiceDriverId);
if (voiceDriverId) { // Let the back end know whether a voice device is selected
jamClient.TrackSetChatEnable(true);
await jamClient.TrackSetChatEnable(true);
} else {
jamClient.TrackSetChatEnable(false);
await jamClient.TrackSetChatEnable(false);
}
if (!audioDriverId) {
console.log("no audio driver ID");
@ -629,8 +630,8 @@
newFtueEnableControls(false);
return;
}
var musicInputs = jamClient.FTUEGetMusicInputs();
var musicOutputs = jamClient.FTUEGetMusicOutputs();
var musicInputs = await jamClient.FTUEGetMusicInputs();
var musicOutputs = await jamClient.FTUEGetMusicOutputs();
// set the music input to the first available input,
// and output to the first available output
@ -649,8 +650,8 @@
}
var result;
if (kin && kout) {
jamClient.FTUESetMusicInput(kin);
jamClient.FTUESetMusicOutput(kout);
await jamClient.FTUESetMusicInput(kin);
await jamClient.FTUESetMusicOutput(kout);
} else {
// TODO FIXME - how to handle a driver selection where we are unable to
// autoset both inputs and outputs? (I'd think this could happen if either
@ -680,22 +681,22 @@
renderVolumes();
logger.debug("Calling FTUESave(" + false + ")");
jamClient.FTUESave(false)
await jamClient.FTUESave(false)
pendingFtueSave = false; // this is not really used in any real fashion. just setting back to false due to batch modify above
setVuCallbacks();
var latency = jamClient.FTUEGetExpectedLatency();
var latency = await jamClient.FTUEGetExpectedLatency();
console.log("FTUEGetExpectedLatency: %o", latency);
newFtueUpdateLatencyView(latency);
});
}
function newFtueSave(persist) {
async function newFtueSave(persist) {
logger.debug("newFtueSave persist(" + persist + ")")
newFtueUpdateLatencyView('loading');
logger.debug("Calling FTUESave(" + persist + ")");
jamClient.FTUESave(persist);
await jamClient.FTUESave(persist);
var latency = jamClient.FTUEGetExpectedLatency();
newFtueUpdateLatencyView(latency);
}
@ -709,7 +710,7 @@
}
// simply tells backend what frontend shows in the UI
function newFtueAsioFrameSizeToBackend($input) {
async function newFtueAsioFrameSizeToBackend($input) {
var val = parseFloat($input.val(), 10);
if (isNaN(val)) {
logger.warn("unable to get value from framesize input: %o", $input.val());
@ -738,35 +739,35 @@
logger.debug("Defaulting WDM input/output");
logger.debug("Calling FTUESetInputLatency(" + defaultInput + ")");
jamClient.FTUESetInputLatency(defaultInput);
await jamClient.FTUESetInputLatency(defaultInput);
logger.debug("Calling FTUESetOutputLatency(" + defaultOutput + ")");
jamClient.FTUESetOutputLatency(defaultOutput);
await jamClient.FTUESetOutputLatency(defaultOutput);
}
logger.debug("Calling FTUESetFrameSize(" + val + ")");
jamClient.FTUESetFrameSize(val);
await jamClient.FTUESetFrameSize(val);
return true;
}
function newFtueAsioInputLatencyToBackend($input) {
async function newFtueAsioInputLatencyToBackend($input) {
var val = parseInt($input.val(), 10);
if (isNaN(val)) {
logger.warn("unable to get value from input latency input: %o", $input.val());
return false;
}
logger.debug("Calling FTUESetInputLatency(" + val + ")");
jamClient.FTUESetInputLatency(val);
await jamClient.FTUESetInputLatency(val);
return true;
}
function newFtueAsioOutputLatencyToBackend($input) {
async function newFtueAsioOutputLatencyToBackend($input) {
var val = parseInt($input.val(), 10);
if (isNaN(val)) {
logger.warn("unable to get value from output latency input: %o", $input.val());
return false;
}
logger.debug("Calling FTUESetOutputLatency(" + val + ")");
jamClient.FTUESetOutputLatency(val);
await jamClient.FTUESetOutputLatency(val);
return true;
}
@ -835,8 +836,9 @@
}
}
function isWDM() {
return jamClient.GetOSAsString() === "Win32" && !jamClient.FTUEHasControlPanel();
async function isWDM() {
let [osaStr, controlPanel] = await Promise.all([jamClient.GetOSAsString(), jamClient.FTUEHasControlPanel()])
return (osaStr === "Win32" && !controlPanel);
}
// Based on OS and Audio Hardware, set Frame/Buffer settings appropriately
@ -942,10 +944,10 @@
}
}
function audioDriverChanged(evt) {
async function audioDriverChanged(evt) {
var $select = $(evt.currentTarget);
currentAudioDriverId = $select.val();
jamClient.FTUESetMusicDevice(currentAudioDriverId);
await jamClient.FTUESetMusicDevice(currentAudioDriverId);
loadAudioDevices();
setAsioSettingsVisibility();
checkValidStateForTesting();
@ -980,13 +982,13 @@
return (audioInput && audioOutput);
}
function setVuCallbacks() {
jamClient.FTUERegisterVUCallbacks(
async function setVuCallbacks() {
await jamClient.FTUERegisterVUCallbacks(
"JK.ftueAudioOutputVUCallback",
"JK.ftueAudioInputVUCallback",
"JK.ftueChatInputVUCallback"
);
jamClient.SetVURefreshRate(200);
await jamClient.SetVURefreshRate(200);
}
function setAsioSettingsVisibility() {
@ -1061,7 +1063,7 @@
};
// Latency Callback
context.JK.ftueLatencyCallback = function (latencyMS) {
context.JK.ftueLatencyCallback = async function (latencyMS) {
// We always show gauge screen if we hit this.
// Clear out the 'timeout' variable.
context.JK.FtueWizard.latencyTimeout = false;
@ -1070,7 +1072,7 @@
context.JK.FtueWizard.latencyMS = latencyMS;
// Unregister callback:
context.jamClient.FTUERegisterLatencyCallback('');
await context.jamClient.FTUERegisterLatencyCallback('');
// Go to 'congrats' screen -- although latency may be too high.
context.JK.app.setWizardStep("6");
};

View File

@ -0,0 +1,48 @@
(function (context, $) {
"use strict";
context.JK = context.JK || {};
context.JK.GearSetupReminder = function (app) {
function showModal(options) {
options = options || {};
$('#gear_setup_reminder').attr('data-mode', 'gear-setup-reminder');
$('body').on('keyup', cancelModal);
$("#gear_setup_reminder a.close-modal").click(function () {
app.layout.closeDialog('gear-setup-reminder');
$('body').off('keyup', cancelModal);
return false;
})
$("#gear_setup_reminder a.setup-gear").click(function () {
app.layout.closeDialog('gear-setup-reminder');
$('body').off('keyup', cancelModal);
window.location.hash = '#/account/audio';
return false;
})
if(!app.layout.isDialogShowing('gear-setup-reminder')) {
app.layout.showDialog('gear-setup-reminder')
}
}
function cancelModal(e) {
if ((e.ctrlKey || e.metaKey) && e.keyCode == 78) {
console.log("update canceled!");
app.layout.closeDialog('gear-setup-reminder');
}
}
// Expose publics
this.show = showModal;
}
return this;
})(window, jQuery);

View File

@ -1,71 +1,88 @@
/**
* Static, simple definitions like strings, hashes, enums
*/
(function(context,$) {
(function (context, $) {
"use strict";
"use strict";
context.JK = context.JK || {};
var logger = context.JK.logger;
context.JK = context.JK || {};
var logger = context.JK.logger;
context.JK.MIDI_TRACK = 100
context.JK.isQWebEngine = !!navigator.userAgent.match("(JamKazam)")
context.JK.CLIENT_ROLE = {
CHILD: 0,
PARENT: 1
}
context.JK.MIDI_TRACK = 100
context.JK.OS = {
WIN32: "Win32",
OSX: "MacOSX",
UNIX: "Unix"
};
context.JK.CLIENT_ROLE = {
CHILD: 0,
PARENT: 1
}
context.JK.ASSIGNMENT = {
CHAT: -2,
OUTPUT: -1,
UNASSIGNED: 0,
TRACK1: 1,
TRACK2: 2
};
context.JK.OS = {
WIN32: "Win32",
OSX: "MacOSX",
UNIX: "Unix"
};
context.JK.VOICE_CHAT = {
NO_CHAT: "0",
CHAT: "1"
};
context.JK.ASSIGNMENT = {
CHAT: -2,
OUTPUT: -1,
UNASSIGNED: 0,
TRACK1: 1,
TRACK2: 2
};
context.JK.AVAILABILITY_US = "United States";
context.JK.MASTER_TRACK = "Master";
context.JK.VOICE_CHAT = {
NO_CHAT: "0",
CHAT: "1"
};
context.JK.EVENTS = {
DIALOG_CLOSED : 'dialog_closed',
SHOW_SIGNUP : 'show_signup',
SHOW_SIGNIN : 'show_signin',
RSVP_SUBMITTED: 'rsvp_submitted',
RSVP_CANCELED : 'rsvp_canceled',
USER_UPDATED : 'user_updated',
SESSION_STARTED : 'session_started',
SESSION_ENDED : 'session_stopped',
FILE_MANAGER_CMD_START : 'file_manager_cmd_start',
FILE_MANAGER_CMD_STOP : 'file_manager_cmd_stop',
FILE_MANAGER_CMD_PROGRESS : 'file_manager_cmd_progress',
FILE_MANAGER_CMD_ASAP_UPDATE : 'file_manager_cmd_asap_update',
MIXER_MODE_CHANGED : 'mixer_mode_changed',
MUTE_SELECTED: 'mute_selected',
SUBSCRIBE_NOTIFICATION: 'subscribe_notification',
CONNECTION_UP: 'connection_up',
CONNECTION_DOWN: 'connection_down',
SCREEN_CHANGED: 'screen_changed',
JAMTRACK_DOWNLOADER_STATE_CHANGED: 'jamtrack_downloader_state',
METRONOME_PLAYBACK_MODE_SELECTED: 'metronome_playback_mode_selected',
CHECKOUT_SIGNED_IN: 'checkout_signed_in',
CHECKOUT_SKIP_SIGN_IN: 'checkout_skip_sign_in',
PREVIEW_PLAYED: 'preview_played',
VST_OPERATION_SELECTED: 'vst_operation_selected',
VST_EFFECT_SELECTED: 'vst_effect_selected',
LESSON_SESSION_ACTION: 'lesson_session_action',
JAMBLASTER_ACTION: 'jamblaster_action'
};
context.JK.AUDIO_FORMATS = ['.mp3', '.ogg', '.wav', '.flac', '.au'];
context.JK.VIDEO_FORMATS = ['.mp4', '.mov'];
context.JK.AUDIO_STORE_TYPE_MIX_AND_STEMS = {
key: 'session_mix_and_steams',
value: 'Session mix + individual parts (streams)',
backendValues: [2, 3]
};
context.JK.AUDIO_STORE_TYPE_MIX_ONLY = {
key: 'session_mix_only',
value: 'Session mix only',
backendValues: [1]
};
context.JK.RECORD_TYPE_AUDIO = 'audio-only'
context.JK.RECORD_TYPE_BOTH = 'audio-video'
context.JK.AVAILABILITY_US = "United States";
context.JK.MASTER_TRACK = "Master";
context.JK.EVENTS = {
DIALOG_CLOSED: 'dialog_closed',
SHOW_SIGNUP: 'show_signup',
SHOW_SIGNIN: 'show_signin',
RSVP_SUBMITTED: 'rsvp_submitted',
RSVP_CANCELED: 'rsvp_canceled',
USER_UPDATED: 'user_updated',
SESSION_STARTED: 'session_started',
SESSION_ENDED: 'session_stopped',
FILE_MANAGER_CMD_START: 'file_manager_cmd_start',
FILE_MANAGER_CMD_STOP: 'file_manager_cmd_stop',
FILE_MANAGER_CMD_PROGRESS: 'file_manager_cmd_progress',
FILE_MANAGER_CMD_ASAP_UPDATE: 'file_manager_cmd_asap_update',
MIXER_MODE_CHANGED: 'mixer_mode_changed',
MUTE_SELECTED: 'mute_selected',
SUBSCRIBE_NOTIFICATION: 'subscribe_notification',
CONNECTION_UP: 'connection_up',
CONNECTION_DOWN: 'connection_down',
SCREEN_CHANGED: 'screen_changed',
JAMTRACK_DOWNLOADER_STATE_CHANGED: 'jamtrack_downloader_state',
METRONOME_PLAYBACK_MODE_SELECTED: 'metronome_playback_mode_selected',
CHECKOUT_SIGNED_IN: 'checkout_signed_in',
CHECKOUT_SKIP_SIGN_IN: 'checkout_skip_sign_in',
PREVIEW_PLAYED: 'preview_played',
VST_OPERATION_SELECTED: 'vst_operation_selected',
VST_EFFECT_SELECTED: 'vst_effect_selected',
LESSON_SESSION_ACTION: 'lesson_session_action',
JAMBLASTER_ACTION: 'jamblaster_action'
};
context.JK.PLAYBACK_MONITOR_MODE = {
MEDIA_FILE: 'MEDIA_FILE',
@ -74,288 +91,288 @@
BROWSER_MEDIA: 'BROWSER_MEDIA'
}
context.JK.ALERT_NAMES = {
NO_EVENT : 0,
BACKEND_ERROR : 1, //generic error - eg P2P message error
BACKEND_MIXER_CHANGE : 2, //event that controls have been regenerated
NO_EVENT: 0,
BACKEND_ERROR: 1, //generic error - eg P2P message error
BACKEND_MIXER_CHANGE: 2, //event that controls have been regenerated
//network related
PACKET_JTR : 3,
PACKET_LOSS : 4,
PACKET_LATE : 5,
PACKET_JTR: 3,
PACKET_LOSS: 4,
PACKET_LATE: 5,
JTR_QUEUE_DEPTH : 6,
JTR_QUEUE_DEPTH: 6,
NETWORK_JTR : 7,
NETWORK_PING : 8,
NETWORK_JTR: 7,
NETWORK_PING: 8,
BITRATE_THROTTLE_WARN : 9,
BANDWIDTH_LOW : 10,
BITRATE_THROTTLE_WARN: 9,
BANDWIDTH_LOW: 10,
//IO related events
INPUT_IO_RATE : 11,
INPUT_IO_JTR : 12,
OUTPUT_IO_RATE : 13,
OUTPUT_IO_JTR : 14,
INPUT_IO_RATE: 11,
INPUT_IO_JTR: 12,
OUTPUT_IO_RATE: 13,
OUTPUT_IO_JTR: 14,
// CPU load related
CPU_LOAD : 15,
DECODE_VIOLATIONS : 16,
CPU_LOAD: 15,
DECODE_VIOLATIONS: 16,
LAST_THRESHOLD : 17,
LAST_THRESHOLD: 17,
WIFI_NETWORK_ALERT : 18, //user or peer is using wifi
NO_VALID_AUDIO_CONFIG : 19, // alert the user to popup a config
AUDIO_DEVICE_NOT_PRESENT : 20, // the audio device is not connected
RECORD_PLAYBACK_STATE : 21, // record/playback events have occurred
RUN_UPDATE_CHECK_BACKGROUND : 22, //this is auto check - do
RUN_UPDATE_CHECK_INTERACTIVE : 23, //this is initiated by user
STUN_EVENT : 24, // system completed stun test... come get the result
DEAD_USER_WARN_EVENT : 25, //the backend is not receiving audio from this peer
DEAD_USER_REMOVE_EVENT : 26, //the backend is removing the user from session as no audio is coming from this peer
WINDOW_CLOSE_BACKGROUND_MODE : 27, //the user has closed the window and the client is now in background mode
WINDOW_OPEN_FOREGROUND_MODE : 28, //the user has opened the window and the client is now in forground mode/
SESSION_LIVEBROADCAST_FAIL : 29, //error of some sort - so can't broadcast
SESSION_LIVEBROADCAST_ACTIVE : 30, //active
SESSION_LIVEBROADCAST_STOPPED : 31, //stopped by server/user
SESSION_LIVEBROADCAST_PINNED : 32, //node pinned by user
SESSION_LIVEBROADCAST_UNPINNED : 33, //node unpinned by user
BACKEND_STATUS_MSG : 34, //status/informational message
LOCAL_NETWORK_VARIANCE_HIGH : 35,//the ping time via a hairpin for the user network is unnaturally high or variable.
WIFI_NETWORK_ALERT: 18, //user or peer is using wifi
NO_VALID_AUDIO_CONFIG: 19, // alert the user to popup a config
AUDIO_DEVICE_NOT_PRESENT: 20, // the audio device is not connected
RECORD_PLAYBACK_STATE: 21, // record/playback events have occurred
RUN_UPDATE_CHECK_BACKGROUND: 22, //this is auto check - do
RUN_UPDATE_CHECK_INTERACTIVE: 23, //this is initiated by user
STUN_EVENT: 24, // system completed stun test... come get the result
DEAD_USER_WARN_EVENT: 25, //the backend is not receiving audio from this peer
DEAD_USER_REMOVE_EVENT: 26, //the backend is removing the user from session as no audio is coming from this peer
WINDOW_CLOSE_BACKGROUND_MODE: 27, //the user has closed the window and the client is now in background mode
WINDOW_OPEN_FOREGROUND_MODE: 28, //the user has opened the window and the client is now in forground mode/
SESSION_LIVEBROADCAST_FAIL: 29, //error of some sort - so can't broadcast
SESSION_LIVEBROADCAST_ACTIVE: 30, //active
SESSION_LIVEBROADCAST_STOPPED: 31, //stopped by server/user
SESSION_LIVEBROADCAST_PINNED: 32, //node pinned by user
SESSION_LIVEBROADCAST_UNPINNED: 33, //node unpinned by user
BACKEND_STATUS_MSG: 34, //status/informational message
LOCAL_NETWORK_VARIANCE_HIGH: 35,//the ping time via a hairpin for the user network is unnaturally high or variable.
//indicates problem with user computer stack or network itself (wifi, antivirus etc)
LOCAL_NETWORK_LATENCY_HIGH : 36,
RECORDING_CLOSE : 37, //update and remove tracks from front-end
PEER_REPORTS_NO_AUDIO_RECV : 38, //letting front-end know audio is not being received from a user in session
SHOW_PREFERENCES : 39, // tell frontend to show preferences dialog
USB_CONNECTED : 40, // tell frontend that a USB device was connected
USB_DISCONNECTED : 41, // tell frontend that a USB device was disconnected
JAM_TRACK_SERVER_ERROR : 42, //error talking with server
BAD_INTERVAL_RATE : 43, //the audio gear is calling back at rate that does not match the expected interval
FIRST_AUDIO_PACKET : 44,// we are receiving audio from peer
NETWORK_PORT_MANGLED : 45, // packet from peer indicates network port is being mangled
NO_GLOBAL_CLOCK_SERVER : 46, //can't reach global clock NTP server
GLOBAL_CLOCK_SYNCED : 47, //clock synced
RECORDING_DONE :48, //the recording writer thread is done
VIDEO_WINDOW_OPENED :49, //video window opened
VIDEO_WINDOW_CLOSED :50,
LOCAL_NETWORK_LATENCY_HIGH: 36,
RECORDING_CLOSE: 37, //update and remove tracks from front-end
PEER_REPORTS_NO_AUDIO_RECV: 38, //letting front-end know audio is not being received from a user in session
SHOW_PREFERENCES: 39, // tell frontend to show preferences dialog
USB_CONNECTED: 40, // tell frontend that a USB device was connected
USB_DISCONNECTED: 41, // tell frontend that a USB device was disconnected
JAM_TRACK_SERVER_ERROR: 42, //error talking with server
BAD_INTERVAL_RATE: 43, //the audio gear is calling back at rate that does not match the expected interval
FIRST_AUDIO_PACKET: 44,// we are receiving audio from peer
NETWORK_PORT_MANGLED: 45, // packet from peer indicates network port is being mangled
NO_GLOBAL_CLOCK_SERVER: 46, //can't reach global clock NTP server
GLOBAL_CLOCK_SYNCED: 47, //clock synced
RECORDING_DONE: 48, //the recording writer thread is done
VIDEO_WINDOW_OPENED: 49, //video window opened
VIDEO_WINDOW_CLOSED: 50,
VST_CHANGED: 51, // VST state changed
SAMPLERATE_CONFIGURATION_BAD: 52,
SHOW_NETWORK_TEST: 53,
LAST_ALERT : 54
LAST_ALERT: 54
}
// recreate eThresholdType enum from MixerDialog.h
context.JK.ALERT_TYPES = {
0: {"title": "", "message": ""}, // NO_EVENT,
1: {"title": "", "message": ""}, // BACKEND_ERROR: generic error - eg P2P message error
2: {"title": "", "message": ""}, // BACKEND_MIXER_CHANGE, - event that controls have been regenerated
3: {"title": "High Packet Jitter", "message": "Your network connection is currently experiencing packet jitter at a level that is too high to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems"}, // PACKET_JTR,
4: {"title": "High Packet Loss", "message": "Your network connection is currently experiencing packet loss at a rate that is too high to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // PACKET_LOSS
5: {"title": "High Packet Late", "message": "Your network connection is currently experiencing packet loss at a rate that is too high to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems"}, // PACKET_LATE,
6: {"title": "Large Jitter Queue", "message": "Your network connection is currently experiencing packet jitter at a level that is too high to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems"}, // JTR_QUEUE_DEPTH,
7: {"title": "High Network Jitter", "message": "Your network connection is currently experiencing network jitter at a level that is too high to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems"}, // NETWORK_JTR,
8: {"title": "High Session Latency", "message": "The latency of your audio device combined with your Internet connection has become high enough to impact your session quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // NETWORK_PING,
9: {"title": "Bandwidth Throttled", "message": "The available bandwidth on your network has diminished, and this may impact your audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems"}, // BITRATE_THROTTLE_WARN,
10:{"title": "Low Bandwidth", "message": "The available bandwidth on your network has become too low, and this may impact your audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // BANDWIDTH_LOW
// recreate eThresholdType enum from MixerDialog.h
context.JK.ALERT_TYPES = {
0: { "title": "", "message": "" }, // NO_EVENT,
1: { "title": "", "message": "" }, // BACKEND_ERROR: generic error - eg P2P message error
2: { "title": "", "message": "" }, // BACKEND_MIXER_CHANGE, - event that controls have been regenerated
3: { "title": "High Packet Jitter", "message": "Your network connection is currently experiencing packet jitter at a level that is too high to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // PACKET_JTR,
4: { "title": "High Packet Loss", "message": "Your network connection is currently experiencing packet loss at a rate that is too high to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // PACKET_LOSS
5: { "title": "High Packet Late", "message": "Your network connection is currently experiencing packet loss at a rate that is too high to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // PACKET_LATE,
6: { "title": "Large Jitter Queue", "message": "Your network connection is currently experiencing packet jitter at a level that is too high to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // JTR_QUEUE_DEPTH,
7: { "title": "High Network Jitter", "message": "Your network connection is currently experiencing network jitter at a level that is too high to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // NETWORK_JTR,
8: { "title": "High Session Latency", "message": "The latency of your audio device combined with your Internet connection has become high enough to impact your session quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // NETWORK_PING,
9: { "title": "Bandwidth Throttled", "message": "The available bandwidth on your network has diminished, and this may impact your audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // BITRATE_THROTTLE_WARN,
10: { "title": "Low Bandwidth", "message": "The available bandwidth on your network has become too low, and this may impact your audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // BANDWIDTH_LOW
// IO related events
11:{"title": "Variable Input Rate", "message": "The input rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // INPUT_IO_RATE
12:{"title": "High Input Jitter", "message": "The input rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems"}, // INPUT_IO_JTR,
13:{"title": "Variable Output Rate", "message": "The output rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems"}, // OUTPUT_IO_RATE
14:{"title": "High Output Jitter", "message": "The output rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems"}, // OUTPUT_IO_JTR,
// IO related events
11: { "title": "Variable Input Rate", "message": "The input rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // INPUT_IO_RATE
12: { "title": "High Input Jitter", "message": "The input rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // INPUT_IO_JTR,
13: { "title": "Variable Output Rate", "message": "The output rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // OUTPUT_IO_RATE
14: { "title": "High Output Jitter", "message": "The output rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // OUTPUT_IO_JTR,
// CPU load related
15: { "title": "CPU Utilization High", "message": "The CPU of your computer is unable to keep up with the current processing load, and this may impact your audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems"}, // CPU_LOAD
16: {"title": "Decode Violations", "message": ""}, // DECODE_VIOLATIONS,
17: {"title": "", "message": ""}, // LAST_THRESHOLD
18: {"title": "Wifi Alert", "message": ""}, // WIFI_NETWORK_ALERT, //user or peer is using wifi
19: {"title": "No Audio Configuration", "message": "You cannot join the session because you do not have a valid audio configuration."}, // NO_VALID_AUDIO_CONFIG,
20: {"title": "", "message": ""}, // AUDIO_DEVICE_NOT_PRESENT, // the audio device is not connected
//20: {"title": "Audio Device Not Present", "message": ""}, // AUDIO_DEVICE_NOT_PRESENT, // the audio device is not connected
21: {"title": "", "message": ""}, // RECORD_PLAYBACK_STATE, // record/playback events have occurred
22: {"title": "", "message": ""}, // RUN_UPDATE_CHECK_BACKGROUND, //this is auto check - do
23: {"title": "", "message": ""}, // RUN_UPDATE_CHECK_INTERACTIVE, //this is initiated by user
24: {"title": "", "message": ""}, // STUN_EVENT, // system completed stun test... come get the result
25: {"title": "No Audio", "message": "Your system is no longer transmitting audio. Other session members are unable to hear you."}, // DEAD_USER_WARN_EVENT, //the backend is not receiving audio from this peer
26: {"title": "No Audio", "message": "Your system is no longer transmitting audio. Other session members are unable to hear you."}, // DEAD_USER_REMOVE_EVENT, //the backend is removing the user from session as no audio is coming from this peer
27: {"title": "", "message": ""}, // WINDOW_CLOSE_BACKGROUND_MODE, //the user has closed the window and the client is now in background mode
28: {"title": "", "message": ""}, // WINDOW_OPEN_FOREGROUND_MODE, //the user has opened the window and the client is now in forground mode/
// CPU load related
15: { "title": "CPU Utilization High", "message": "The CPU of your computer is unable to keep up with the current processing load, and this may impact your audio quality. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // CPU_LOAD
16: { "title": "Decode Violations", "message": "" }, // DECODE_VIOLATIONS,
17: { "title": "", "message": "" }, // LAST_THRESHOLD
18: { "title": "Wifi Alert", "message": "" }, // WIFI_NETWORK_ALERT, //user or peer is using wifi
19: { "title": "No Audio Configuration", "message": "You cannot join the session because you do not have a valid audio configuration." }, // NO_VALID_AUDIO_CONFIG,
20: { "title": "", "message": "" }, // AUDIO_DEVICE_NOT_PRESENT, // the audio device is not connected
//20: {"title": "Audio Device Not Present", "message": ""}, // AUDIO_DEVICE_NOT_PRESENT, // the audio device is not connected
21: { "title": "", "message": "" }, // RECORD_PLAYBACK_STATE, // record/playback events have occurred
22: { "title": "", "message": "" }, // RUN_UPDATE_CHECK_BACKGROUND, //this is auto check - do
23: { "title": "", "message": "" }, // RUN_UPDATE_CHECK_INTERACTIVE, //this is initiated by user
24: { "title": "", "message": "" }, // STUN_EVENT, // system completed stun test... come get the result
25: { "title": "No Audio", "message": "Your system is no longer transmitting audio. Other session members are unable to hear you." }, // DEAD_USER_WARN_EVENT, //the backend is not receiving audio from this peer
26: { "title": "No Audio", "message": "Your system is no longer transmitting audio. Other session members are unable to hear you." }, // DEAD_USER_REMOVE_EVENT, //the backend is removing the user from session as no audio is coming from this peer
27: { "title": "", "message": "" }, // WINDOW_CLOSE_BACKGROUND_MODE, //the user has closed the window and the client is now in background mode
28: { "title": "", "message": "" }, // WINDOW_OPEN_FOREGROUND_MODE, //the user has opened the window and the client is now in forground mode/
29: {"title": "Failed to Broadcast", "message": ""}, // SESSION_LIVEBROADCAST_FAIL, //error of some sort - so can't broadcast
30: {"title": "", "message": ""}, // SESSION_LIVEBROADCAST_ACTIVE, //active
31: {"title": "", "message": ""}, // SESSION_LIVEBROADCAST_STOPPED, //stopped by server/user
32: {"title": "Client Pinned", "message": "This client will be the source of a broadcast."}, // SESSION_LIVEBROADCAST_PINNED, //node pinned by user
33: {"title": "Client No Longer Pinned", "message": "This client is no longer designated as the source of the broadcast."}, // SESSION_LIVEBROADCAST_UNPINNED, //node unpinned by user
29: { "title": "Failed to Broadcast", "message": "" }, // SESSION_LIVEBROADCAST_FAIL, //error of some sort - so can't broadcast
30: { "title": "", "message": "" }, // SESSION_LIVEBROADCAST_ACTIVE, //active
31: { "title": "", "message": "" }, // SESSION_LIVEBROADCAST_STOPPED, //stopped by server/user
32: { "title": "Client Pinned", "message": "This client will be the source of a broadcast." }, // SESSION_LIVEBROADCAST_PINNED, //node pinned by user
33: { "title": "Client No Longer Pinned", "message": "This client is no longer designated as the source of the broadcast." }, // SESSION_LIVEBROADCAST_UNPINNED, //node unpinned by user
34: {"title": "", "message": ""}, // BACKEND_STATUS_MSG, //status/informational message
35: {"title": "LAN Unpredictable", "message": "Your local network is adding considerable variance to transmit times. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems"}, // LOCAL_NETWORK_VARIANCE_HIGH,//the ping time via a hairpin for the user network is unnaturally high or variable.
34: { "title": "", "message": "" }, // BACKEND_STATUS_MSG, //status/informational message
35: { "title": "LAN Unpredictable", "message": "Your local network is adding considerable variance to transmit times. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // LOCAL_NETWORK_VARIANCE_HIGH,//the ping time via a hairpin for the user network is unnaturally high or variable.
//indicates problem with user computer stack or network itself (wifi, antivirus etc)
36: {"title": "LAN High Latency", "message": "Your local network is adding considerable latency. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems"}, // LOCAL_NETWORK_LATENCY_HIGH,
37: {"title": "", "message": ""}, // RECORDING_CLOSE, //update and remove tracks from front-end
38: {"title": "No Audio Sent", "message": ""}, // PEER_REPORTS_NO_AUDIO_RECV, //update and remove tracks from front-end
39: {"title": "", "message": ""}, // SHOW_PREFERENCES, //show preferences dialog
40: {"title": "", "message": ""}, // USB_CONNECTED
41: {"title": "", "message": ""}, // USB_DISCONNECTED, // tell frontend that a USB device was disconnected
42: {"title": "", "message": ""}, // JAM_TRACK_SERVER_ERROR
43: {"title": "", "message": ""}, // BAD_INTERVAL_RATE
44: {"title": "", "message": ""}, // FIRST_AUDIO_PACKET
45: {"title": "", "message": ""}, // NETWORK_PORT_MANGLED
46: {"title": "", "message": ""}, // NO_GLOBAL_CLOCK_SERVER
47: {"title": "", "message": ""}, // GLOBAL_CLOCK_SYNCED
48: {"title": "", "message": ""}, // RECORDING_DONE
49: {"title": "", "message": ""}, // VIDEO_WINDOW_OPENED
50: {"title": "", "message": ""}, // VIDEO_WINDOW_CLOSED
51: {"title": "", "message": ""}, // VST_CHANGED
52: {"title": "", "message": ""}, // SAMPLERATE_CONFIGURATION_BAD
53: {"title": "", "message": ""}, // SHOW_NETWORK_TEST
54: {"title": "", "message": ""} // LAST_ALERT
};
//indicates problem with user computer stack or network itself (wifi, antivirus etc)
36: { "title": "LAN High Latency", "message": "Your local network is adding considerable latency. For troubleshooting tips, click the '?'.", help: "https://jamkazam.desk.com/customer/portal/articles/1288778-troubleshoot-session-quality-problems" }, // LOCAL_NETWORK_LATENCY_HIGH,
37: { "title": "", "message": "" }, // RECORDING_CLOSE, //update and remove tracks from front-end
38: { "title": "No Audio Sent", "message": "" }, // PEER_REPORTS_NO_AUDIO_RECV, //update and remove tracks from front-end
39: { "title": "", "message": "" }, // SHOW_PREFERENCES, //show preferences dialog
40: { "title": "", "message": "" }, // USB_CONNECTED
41: { "title": "", "message": "" }, // USB_DISCONNECTED, // tell frontend that a USB device was disconnected
42: { "title": "", "message": "" }, // JAM_TRACK_SERVER_ERROR
43: { "title": "", "message": "" }, // BAD_INTERVAL_RATE
44: { "title": "", "message": "" }, // FIRST_AUDIO_PACKET
45: { "title": "", "message": "" }, // NETWORK_PORT_MANGLED
46: { "title": "", "message": "" }, // NO_GLOBAL_CLOCK_SERVER
47: { "title": "", "message": "" }, // GLOBAL_CLOCK_SYNCED
48: { "title": "", "message": "" }, // RECORDING_DONE
49: { "title": "", "message": "" }, // VIDEO_WINDOW_OPENED
50: { "title": "", "message": "" }, // VIDEO_WINDOW_CLOSED
51: { "title": "", "message": "" }, // VST_CHANGED
52: { "title": "", "message": "" }, // SAMPLERATE_CONFIGURATION_BAD
53: { "title": "", "message": "" }, // SHOW_NETWORK_TEST
54: { "title": "", "message": "" } // LAST_ALERT
};
// add the alert's name to the ALERT_TYPES structure
context._.each(context.JK.ALERT_NAMES, function(alert_code, alert_name) {
var alert_data = context.JK.ALERT_TYPES[alert_code];
alert_data.name = alert_name;
})
// add the alert's name to the ALERT_TYPES structure
context._.each(context.JK.ALERT_NAMES, function (alert_code, alert_name) {
var alert_data = context.JK.ALERT_TYPES[alert_code];
alert_data.name = alert_name;
})
context.JK.MAX_TRACKS = 6;
context.JK.MAX_OUTPUTS = 2;
context.JK.MAX_TRACKS = 6;
context.JK.MAX_OUTPUTS = 2;
// TODO: store these client_id values in instruments table, or store
// server_id as the client_id to prevent maintenance nightmares. As it's
// set up now, we will have to deploy each time we add new instruments.
context.JK.server_to_client_instrument_map = {
"Acoustic Guitar": { "client_id": 10, "server_id": "acoustic guitar" },
"Bass Guitar": { "client_id": 20, "server_id": "bass guitar" },
"Computer": { "client_id": 30, "server_id": "computer" },
"Drums": { "client_id": 40, "server_id": "drums" },
"Percussion": { "client_id": 41, "server_id": "percussion" },
"Electric Guitar": { "client_id": 50, "server_id": "electric guitar" },
"Keyboard": { "client_id": 60, "server_id": "keyboard" },
"Piano": { "client_id": 61, "server_id": "piano" },
"Double Bass": { "client_id": 62, "server_id": "double bass" },
"Voice": { "client_id": 70, "server_id": "voice" },
"Flute": { "client_id": 80, "server_id": "flute" },
"Clarinet": { "client_id": 90, "server_id": "clarinet" },
"Saxophone": { "client_id": 100, "server_id": "saxophone" },
"Trumpet": { "client_id": 110, "server_id": "trumpet" },
"Violin": { "client_id": 120, "server_id": "violin" },
"Trombone": { "client_id": 130, "server_id": "trombone" },
"Banjo": { "client_id": 140, "server_id": "banjo" },
"Harmonica": { "client_id": 150, "server_id": "harmonica" },
"Accordion": { "client_id": 160, "server_id": "accordion" },
"French Horn": { "client_id": 170, "server_id": "french horn" },
"Euphonium": { "client_id": 180, "server_id": "euphonium" },
"Tuba": { "client_id": 190, "server_id": "tuba" },
"Oboe": { "client_id": 200, "server_id": "oboe" },
"Ukulele": { "client_id": 210, "server_id": "ukulele" },
"Cello": { "client_id": 220, "server_id": "cello" },
"Viola": { "client_id": 230, "server_id": "viola" },
"Mandolin": { "client_id": 240, "server_id": "mandolin" },
"Other": { "client_id": 250, "server_id": "other" }
};
// server_id as the client_id to prevent maintenance nightmares. As it's
// set up now, we will have to deploy each time we add new instruments.
context.JK.server_to_client_instrument_map = {
"Acoustic Guitar": { "client_id": 10, "server_id": "acoustic guitar" },
"Bass Guitar": { "client_id": 20, "server_id": "bass guitar" },
"Computer": { "client_id": 30, "server_id": "computer" },
"Drums": { "client_id": 40, "server_id": "drums" },
"Percussion": { "client_id": 41, "server_id": "percussion" },
"Electric Guitar": { "client_id": 50, "server_id": "electric guitar" },
"Keyboard": { "client_id": 60, "server_id": "keyboard" },
"Piano": { "client_id": 61, "server_id": "piano" },
"Double Bass": { "client_id": 62, "server_id": "double bass" },
"Voice": { "client_id": 70, "server_id": "voice" },
"Flute": { "client_id": 80, "server_id": "flute" },
"Clarinet": { "client_id": 90, "server_id": "clarinet" },
"Saxophone": { "client_id": 100, "server_id": "saxophone" },
"Trumpet": { "client_id": 110, "server_id": "trumpet" },
"Violin": { "client_id": 120, "server_id": "violin" },
"Trombone": { "client_id": 130, "server_id": "trombone" },
"Banjo": { "client_id": 140, "server_id": "banjo" },
"Harmonica": { "client_id": 150, "server_id": "harmonica" },
"Accordion": { "client_id": 160, "server_id": "accordion" },
"French Horn": { "client_id": 170, "server_id": "french horn" },
"Euphonium": { "client_id": 180, "server_id": "euphonium" },
"Tuba": { "client_id": 190, "server_id": "tuba" },
"Oboe": { "client_id": 200, "server_id": "oboe" },
"Ukulele": { "client_id": 210, "server_id": "ukulele" },
"Cello": { "client_id": 220, "server_id": "cello" },
"Viola": { "client_id": 230, "server_id": "viola" },
"Mandolin": { "client_id": 240, "server_id": "mandolin" },
"Other": { "client_id": 250, "server_id": "other" }
};
context.JK.client_to_server_instrument_map = {
10: { "server_id": "acoustic guitar" },
20: { "server_id": "bass guitar" },
30: { "server_id": "computer" },
40: { "server_id": "drums" },
41: { "server_id": "percussion" },
50: { "server_id": "electric guitar" },
60: { "server_id": "keyboard" },
61: { "server_id": "piano"} ,
62: { "server_id": "double bass"} ,
70: { "server_id": "voice" },
80: { "server_id": "flute" },
90: { "server_id": "clarinet" },
100: { "server_id": "saxophone" },
110: { "server_id": "trumpet" },
120: { "server_id": "violin" },
130: { "server_id": "trombone" },
140: { "server_id": "banjo" },
150: { "server_id": "harmonica" },
160: { "server_id": "accordion" },
170: { "server_id": "french horn" },
180: { "server_id": "euphonium" },
190: { "server_id": "tuba" },
200: { "server_id": "oboe" },
210: { "server_id": "ukulele" },
220: { "server_id": "cello" },
230: { "server_id": "viola" },
240: { "server_id": "mandolin" },
250: { "server_id": "other" }
};
context.JK.client_to_server_instrument_map = {
10: { "server_id": "acoustic guitar" },
20: { "server_id": "bass guitar" },
30: { "server_id": "computer" },
40: { "server_id": "drums" },
41: { "server_id": "percussion" },
50: { "server_id": "electric guitar" },
60: { "server_id": "keyboard" },
61: { "server_id": "piano" },
62: { "server_id": "double bass" },
70: { "server_id": "voice" },
80: { "server_id": "flute" },
90: { "server_id": "clarinet" },
100: { "server_id": "saxophone" },
110: { "server_id": "trumpet" },
120: { "server_id": "violin" },
130: { "server_id": "trombone" },
140: { "server_id": "banjo" },
150: { "server_id": "harmonica" },
160: { "server_id": "accordion" },
170: { "server_id": "french horn" },
180: { "server_id": "euphonium" },
190: { "server_id": "tuba" },
200: { "server_id": "oboe" },
210: { "server_id": "ukulele" },
220: { "server_id": "cello" },
230: { "server_id": "viola" },
240: { "server_id": "mandolin" },
250: { "server_id": "other" }
};
context.JK.instrument_id_to_instrument = {};
context.JK.instrument_id_to_instrument = {};
context.JK.server_to_client_instrument_alpha = [];
context.JK.server_to_client_instrument_alpha = [];
(function() {
$.each(context.JK.server_to_client_instrument_map, function(key, value) {
context.JK.instrument_id_to_instrument[value.server_id] = { client_id: value.client_id, display: key }
context.JK.server_to_client_instrument_alpha.push({ client_id: value.client_id, display: key, server_id: value.server_id })
});
(function () {
$.each(context.JK.server_to_client_instrument_map, function (key, value) {
context.JK.instrument_id_to_instrument[value.server_id] = { client_id: value.client_id, display: key }
context.JK.server_to_client_instrument_alpha.push({ client_id: value.client_id, display: key, server_id: value.server_id })
});
context.JK.server_to_client_instrument_alpha.sort(function(a, b){
if ( a.display < b.display )
return -1;
if ( a.display > b.display )
return 1;
return 0;
});
})();
context.JK.server_to_client_instrument_alpha.sort(function (a, b) {
if (a.display < b.display)
return -1;
if (a.display > b.display)
return 1;
return 0;
});
})();
context.JK.entityToPrintable = {
music_session: "music session",
slot: "Requested time"
}
context.JK.AUDIO_DEVICE_BEHAVIOR = {
MacOSX_builtin: {
display: 'MacOSX Built-In',
shortName: 'Built-In',
videoURL: "https://www.youtube.com/watch?v=7-9PW50ygHk",
showKnobs: true,
showASIO: false
},
MacOSX_interface: {
display: 'MacOSX external interface',
shortName: 'External',
videoURL: "https://www.youtube.com/watch?v=7BLld6ogm14",
showKnobs: true,
showASIO: false
},
Win32_wdm: {
display: 'Windows WDM',
shortName : 'WDM',
videoURL: "https://www.youtube.com/watch?v=L36UBkAV14c",
showKnobs: true,
showASIO: false
},
Win32_asio: {
display: 'Windows ASIO',
shortName : 'ASIO',
videoURL: "https://www.youtube.com/watch?v=PGUmISTVVMY",
showKnobs: true,
showASIO: true
},
Win32_asio4all: {
display: 'Windows ASIO4ALL',
shortName : 'ASIO4ALL',
videoURL: "https://www.youtube.com/watch?v=PGUmISTVVMY",
showKnobs: true,
showASIO: true
},
Linux: {
display: 'Linux',
shortName : 'linux',
videoURL: undefined,
showKnobs: true,
showASIO: false
}
context.JK.entityToPrintable = {
music_session: "music session",
slot: "Requested time"
}
context.JK.AUDIO_DEVICE_BEHAVIOR = {
MacOSX_builtin: {
display: 'MacOSX Built-In',
shortName: 'Built-In',
videoURL: "https://www.youtube.com/watch?v=7-9PW50ygHk",
showKnobs: true,
showASIO: false
},
MacOSX_interface: {
display: 'MacOSX external interface',
shortName: 'External',
videoURL: "https://www.youtube.com/watch?v=7BLld6ogm14",
showKnobs: true,
showASIO: false
},
Win32_wdm: {
display: 'Windows WDM',
shortName: 'WDM',
videoURL: "https://www.youtube.com/watch?v=L36UBkAV14c",
showKnobs: true,
showASIO: false
},
Win32_asio: {
display: 'Windows ASIO',
shortName: 'ASIO',
videoURL: "https://www.youtube.com/watch?v=PGUmISTVVMY",
showKnobs: true,
showASIO: true
},
Win32_asio4all: {
display: 'Windows ASIO4ALL',
shortName: 'ASIO4ALL',
videoURL: "https://www.youtube.com/watch?v=PGUmISTVVMY",
showKnobs: true,
showASIO: true
},
Linux: {
display: 'Linux',
shortName: 'linux',
videoURL: undefined,
showKnobs: true,
showASIO: false
}
}
context.JK.MIX_MODES = {
MASTER: true,
@ -364,23 +381,27 @@
/** NAMED_MESSAGES means messages that we show to the user (dialogs/banners/whatever), that we have formally named */
context.JK.NAMED_MESSAGES = {
MASTER_VS_PERSONAL_MIX : 'master_vs_personal_mix',
HOWTO_USE_VIDEO_NOSHOW : 'how-to-use-video',
CONFIGURE_VIDEO_NOSHOW : 'configure-video',
TEACHER_MUSICIAN_PROFILE : 'teacher-musician-profile'
MASTER_VS_PERSONAL_MIX: 'master_vs_personal_mix',
HOWTO_USE_VIDEO_NOSHOW: 'how-to-use-video',
CONFIGURE_VIDEO_NOSHOW: 'configure-video',
TEACHER_MUSICIAN_PROFILE: 'teacher-musician-profile'
}
context.JK.ALERT_MESSAGES = {
OBS_UNAVAILABLE: 'To make a video recording in JamKazam, you must first install and configure OBS software. Click the link below for a help article that explains how to do this. <a href="" target="_blank" title="Install OBS">View Help Article</a>'
}
context.JK.ChannelGroupIds = {
"MasterGroup": 0,
"MonitorGroup": 1,
"MasterCatGroup" : 2,
"MonitorCatGroup" : 3,
"MasterCatGroup": 2,
"MonitorCatGroup": 3,
"AudioInputMusicGroup": 4,
"AudioInputChatGroup": 5,
"MediaTrackGroup": 6,
"StreamOutMusicGroup": 7,
"StreamOutChatGroup": 8,
"StreamOutMediaGroup" : 9,
"StreamOutMediaGroup": 9,
"UserMusicInputGroup": 10,
"UserChatInputGroup": 11,
"UserMediaInputGroup": 12,
@ -416,13 +437,13 @@
18: "PeerMidiInputMusicGroup"
}
context.JK.CategoryGroupIds = {
"AudioInputMusic" : "AudioInputMusic",
"AudioInputChat" : "AudioInputChat",
"UserMusic" : "UserMusic",
"UserChat" : "UserChat",
"UserMedia" : "UserMedia",
"MediaTrack" : "MediaTrack",
"Metronome" : "Metronome"
"AudioInputMusic": "AudioInputMusic",
"AudioInputChat": "AudioInputChat",
"UserMusic": "UserMusic",
"UserChat": "UserChat",
"UserMedia": "UserMedia",
"MediaTrack": "MediaTrack",
"Metronome": "Metronome"
}
})(window,jQuery);
})(window, jQuery);

View File

@ -56,6 +56,28 @@
});
}
// function createScheduledSessionPromise(options) {
// return new Promise((resolve, reject) => {
// $.ajax({
// type: "POST",
// dataType: "json",
// contentType: 'application/json',
// url: "/api/sessions",
// processData: false,
// data: JSON.stringify(options)
// })
// .done(resp => {
// console.log("Session created", resp);
// resolve(resp)
// })
// .fail(error => {
// console.log("Session create error", error);
// reject(error)
// })
// })
// }
function getBroadcastNotification(options) {
var userId = getId(options);
return $.ajax({
@ -131,6 +153,29 @@
});
}
function joinSessionPromise(options) {
console.log('joinSessionOpts', options);
var sessionId = options["session_id"];
delete options["session_id"];
return new Promise(function(resolve, reject){
$.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: "/api/sessions/" + sessionId + "/participants",
data: JSON.stringify(options),
processData: false
})
.done(function(resp){
resolve(resp);
})
.fail(function(xhr){
reject(xhr)
})
})
}
function cancelSession(options) {
var sessionId = options["session_id"];
delete options["session_id"];
@ -220,6 +265,26 @@
});
}
function getSessionHistoryPromise(id, includePending) {
var includeFlag = 'false';
if (includePending) {
includeFlag = 'true';
}
return new Promise(function(resolve, reject){
$.ajax({
type: "GET",
dataType: "json",
url: '/api/sessions/' + id + '/history?includePending=' + includeFlag,
contentType: 'application/json',
processData: false
}).done(function(resp){
resolve(resp)
}).fail(function(err){
reject(err)
})
})
}
function addSessionInfoComment(sessionId, comment) {
return $.ajax({
url: '/api/sessions/' + sessionId + "/details/comments",
@ -1113,17 +1178,24 @@
})
}
function getUserSyncs(options) {
async function getUserSyncs(options) {
if (!options) {
options = {};
}
var userId = getId(options)
return $.ajax({
type: 'GET',
dataType: "json",
url: "/api/users/" + userId + "/syncs?" + $.param(options),
processData: false
})
try {
return await $.ajax({
type: 'GET',
dataType: "json",
url: "/api/users/" + userId + "/syncs?" + $.param(options),
processData: false
})
} catch (error) {
console.error(error);
throw(error)
}
}
function getUserSync(options) {
@ -1302,6 +1374,23 @@
})
}
function startRecordingPromise(options) {
return new Promise(function(resolve, reject){
$.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: "/api/recordings/start",
data: JSON.stringify(options)
}).done(function(resp){
resolve(resp)
}).fail(function(jqXHR){
reject(jqXHR)
})
})
}
function stopRecording(options) {
var recordingId = options["id"]
@ -1354,6 +1443,8 @@
function getRecording(options) {
var recordingId = options["id"];
console.log("getRecording: ", options)
return $.ajax({
type: "GET",
dataType: "json",
@ -1362,6 +1453,24 @@
});
}
function getRecordingPromise(options) {
return new Promise(function(resolve, reject){
console.log("getRecordingPromise: ", options)
var recordingId = options["id"];
$.ajax({
type: "GET",
dataType: "json",
contentType: 'application/json',
url: "/api/recordings/" + recordingId
}).done(function(resp){
resolve(resp)
}).fail(function(jqXHR){
reject(jqXHR)
});
})
}
function getClaimedRecordings(options) {
return $.ajax({
type: "GET",
@ -1372,6 +1481,23 @@
});
}
function getClaimedRecordingsPromise(options) {
return new Promise(function(resolve, reject){
$.ajax({
type: "GET",
dataType: "json",
contentType: 'application/json',
url: "/api/claimed_recordings",
data: options
}).done(function(data, textStatus, jqXHR){
resolve([data, textStatus, jqXHR]);
}).fail(function(jqXHR, textStatus, errorMessage){
reject([jqXHR, textStatus, errorMessage]);
});
});
}
function getClaimedRecording(id) {
return $.ajax({
type: "GET",
@ -1404,11 +1530,11 @@
function deleteRecordingClaim(id) {
return $.ajax({
type: "DELETE",
dataType: "json",
contentType: 'application/json',
url: "/api/recordings/" + id + "/claim"
});
type: "DELETE",
dataType: "json",
contentType: 'application/json',
url: "/api/recordings/" + id + "/claim"
});
}
function claimRecording(options) {
@ -1429,13 +1555,22 @@
delete options["id"];
delete options["claimed_recording_id"];
return $.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: "/api/sessions/" + musicSessionId + "/claimed_recording/" + claimedRecordingId + "/start",
data: JSON.stringify(options)
return new Promise(function(resolve, reject){
$.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: "/api/sessions/" + musicSessionId + "/claimed_recording/" + claimedRecordingId + "/start",
data: JSON.stringify(options)
})
.done(function(resp){
resolve(resp);
}).fail(function(jqXHR){
reject(jqXHR)
})
})
}
function stopPlayClaimedRecording(options) {
@ -1456,13 +1591,20 @@
function openBackingTrack(options) {
var musicSessionId = options["id"];
delete options["id"];
return $.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: "/api/sessions/" + musicSessionId + "/backing_tracks/open",
data: JSON.stringify(options)
return new Promise(function(resolve, reject){
$.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: "/api/sessions/" + musicSessionId + "/backing_tracks/open",
data: JSON.stringify(options)
})
.done(function(resp){
resolve(resp);
})
.fail(function(xhr){
reject(xhr)
})
})
}
@ -1611,13 +1753,20 @@
function closeMetronome(options) {
var musicSessionId = options["id"];
delete options["id"];
return $.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: "/api/sessions/" + musicSessionId + "/metronome/close",
data: JSON.stringify(options)
return new Promise((resolve, reject) => {
$.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: "/api/sessions/" + musicSessionId + "/metronome/close",
data: JSON.stringify(options)
})
.done((resp) => {
resolve(resp)
})
.fail(jqXHR => {
reject(jqXHR);
})
})
}
@ -2968,6 +3117,7 @@
this.quietBroadcastNotification = quietBroadcastNotification;
this.legacyJoinSession = legacyJoinSession;
this.joinSession = joinSession;
this.joinSessionPromise = joinSessionPromise;
this.cancelSession = cancelSession;
this.updateScheduledSession = updateScheduledSession;
this.getUserDetail = getUserDetail;
@ -3047,11 +3197,13 @@
this.updateJoinRequest = updateJoinRequest;
this.updateUser = updateUser;
this.startRecording = startRecording;
this.startRecordingPromise = startRecordingPromise;
this.stopRecording = stopRecording;
this.getRecording = getRecording;
this.getRecordedTrack = getRecordedTrack;
this.getRecordedBackingTrack = getRecordedBackingTrack;
this.getClaimedRecordings = getClaimedRecordings;
this.getClaimedRecordingsPromise = getClaimedRecordingsPromise;
this.getClaimedRecording = getClaimedRecording;
this.updateClaimedRecording = updateClaimedRecording;
this.deleteClaimedRecording = deleteClaimedRecording;
@ -3216,6 +3368,9 @@
this.listInvoices = listInvoices;
this.getVideoConferencingRoomUrl = getVideoConferencingRoomUrl;
this.getLatencyToUsers = getLatencyToUsers;
this.getSessionHistoryPromise = getSessionHistoryPromise;
this.getRecordingPromise = getRecordingPromise;
return this;
};
})(window, jQuery);

View File

@ -91,8 +91,8 @@
/**
* This occurs when a new download from a recording has become available
*/
function downloadAvailable() {
context.jamClient.OnDownloadAvailable();
async function downloadAvailable() {
await context.jamClient.OnDownloadAvailable();
}
/**
@ -352,6 +352,18 @@
return;
}
//force user to new jamtrack page (beta site)
if(hash && hash == '#/jamtrack') {
var urlToOpen = gon.spa_origin + '/jamtracks';
if(gon.isNativeClient) {
context.JK.popExternalLink(urlToOpen);
}else{
context.location.href = urlToOpen;
}
hash = '#/home';
}
var url = '/client#/' + screen;
if (hash) {
url = hash;
@ -406,19 +418,18 @@
context.JK.JamServer.updateNotificationSeen(notificationId, notificationCreatedAt);
}
this.unloadFunction = function () {
this.unloadFunction = async function () {
logger.debug("window.unload function called.");
context.JK.JamServer.close(false);
if (context.jamClient) {
// Unregister for callbacks.
context.jamClient.RegisterRecordingCallbacks("", "", "", "", "");
context.jamClient.SessionRegisterCallback("");
context.jamClient.SessionSetAlertCallback("");
context.jamClient.FTUERegisterVUCallbacks("", "", "");
context.jamClient.FTUERegisterLatencyCallback("");
context.jamClient.RegisterVolChangeCallBack("");
await context.jamClient.RegisterRecordingCallbacks("", "", "", "", "");
await context.jamClient.SessionSetAlertCallback("");
await context.jamClient.FTUERegisterVUCallbacks("", "", "");
await context.jamClient.FTUERegisterLatencyCallback("");
await context.jamClient.RegisterVolChangeCallBack("");
}
};
@ -475,6 +486,9 @@
this.clientId = null;
this.initialRouting = initialRouting;
//video server
this.videoIsOngoing = false;
$(document).triggerHandler('JAMKAZAM_CONSTRUCTED', {app:this})
return this;
};

View File

@ -85,6 +85,7 @@
//= require ../web/affiliate_program
//= require ../web/affiliate_links
//= require fakeJamClient
//= require fakeJamClientProxy
//= require fakeJamClientMessages
//= require fakeJamClientRecordings
//= require JamServer

View File

@ -43,10 +43,10 @@
url: url,
data: JSON.stringify(data),
processData:false,
success: function(response) {
success: async function(response) {
context.JK.Sessions.JoinSession(session_id);
if (client !== undefined) {
client.JoinSession({ sessionID: session_id });
await client.JoinSession({ sessionID: session_id });
}
context.JK.refreshMusicSession(session_id);
},

View File

@ -38,7 +38,7 @@
var value = options.mode;
setValue(options.mode, $parent)
function onModeSelected() {
async function onModeSelected() {
var $li = $(this);
var playbackMode = $li.attr('data-playback-option');
@ -50,7 +50,7 @@
else {
// if no playback mode, then this must be an attempt to open metronome window
close();
context.jamClient.SessionShowMetronomeGui();
await context.jamClient.SessionShowMetronomeGui();
}
return false;
};

View File

@ -482,6 +482,18 @@
var destination = $(evt.currentTarget).attr('layout-link');
var $destination = $('[layout-id="' + destination + '"]');
//force user to the new site if they click on the jamtrack tile
if(destination === "jamtrack") {
var urlToOpen = gon.spa_origin + '/jamtracks';
if(gon.isNativeClient) {
context.JK.popExternalLink(urlToOpen);
return;
}else{
window.open(urlToOpen, '_blank');
return;
}
}
var destinationType = $destination.attr("layout");
if (destinationType === "screen") {
if(!context.JK.currentUserId && !$destination.is('.no-login-required')) {

View File

@ -21,10 +21,10 @@
$.ajax({
type: "DELETE",
url: url
}).done(function (response) {
}).done(async function (response) {
context.JK.Sessions.LeaveSession(session_id);
if (client !== undefined) {
client.LeaveSession({ sessionID: session_id });
await client.LeaveSession({ sessionID: session_id });
}
});
};

View File

@ -254,9 +254,10 @@ context.JK.MusicianSearchFilter = class MusicianSearchFilter extends BaseSearchF
super()
loadSearchFilter: (sFilter) =>
super(sFilter)
@searchFilter = JSON.parse(sFilter)
@searchFilter = JSON.parse(sFilter)
args =
interests: this.filterData().interests
skill_level: this.filterData().skill_level
@ -822,7 +823,7 @@ context.JK.BandSearchFilter = class BandSearchFilter extends BaseSearchFilter
context.JK.bindHoverEvents()
return
_bindFollowBand: () =>
objThis = this
@screen.find('.search-m-follow').on 'click', (evt) ->

View File

@ -0,0 +1,117 @@
/**
* meta_tracking.js
* A standalone module to capture and persist Meta attribution signals (fbclid, _fbp) in cookies.
*
* Logic adapted for legacy environment (no React hooks).
* - Checks URL for `fbclid` and sets `_fbc` cookie.
* - Checks for `_fbp` cookie; if missing, generates and sets it.
*/
(function (window, document) {
'use strict';
var MetaTracking = {
init: function () {
var location = window.location;
this.handleFbc(location.search);
this.handleFbp();
this.handleUtm(location.search);
},
// 1. Parsing and storing _fbc (Click ID)
handleFbc: function (searchParams) {
var fbclid = this.getQueryParam('fbclid', searchParams);
if (fbclid) {
var version = 'fb';
var subdomainIndex = 1; // 1 = example.com
var creationTime = new Date().getTime(); // Unix timestamp in ms
// Format: fb.1.timestamp.id
var fbcValue = version + '.' + subdomainIndex + '.' + creationTime + '.' + fbclid;
this.setCookie('_fbc', fbcValue, 90);
}
},
handleUtm: function (searchParams) {
var self = this;
if (!searchParams) return;
// Logically, we want to capture all utm_ parameters.
// We can either iterate a list or dynamic regex.
// Given the requirement to be robust, let's look for "utm_"
var query = searchParams.substring(1); // remove '?'
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (pair.length === 2) {
var key = decodeURIComponent(pair[0]);
var value = decodeURIComponent(pair[1]);
if (key.indexOf('utm_') === 0) {
self.setCookie(key, value, 90);
}
}
}
},
// 2. Handling _fbp (Browser ID)
handleFbp: function () {
if (!this.getCookie('_fbp')) {
var version = 'fb';
var subdomainIndex = 1;
var creationTime = new Date().getTime();
var randomInt = Math.floor(Math.random() * 10000000000); // 10-digit random number
// Format: fb.1.timestamp.randomDigits
var fbpValue = version + '.' + subdomainIndex + '.' + creationTime + '.' + randomInt;
this.setCookie('_fbp', fbpValue, 90);
}
},
// Helper: Get query param by name
getQueryParam: function (name, search) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
var results = regex.exec(search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
},
// Helper: Set cookie
setCookie: function (name, value, days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
// Ensure path is root and domain is included if needed (defaults to current host)
document.cookie = name + "=" + (value || "") + expires + "; path=/";
},
// Helper: Get cookie
getCookie: function (name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
};
// Initialize on ready
if (document.readyState === 'complete' || document.readyState === 'interactive') {
MetaTracking.init();
} else {
// IE9+ support for DOMContentLoaded
document.addEventListener('DOMContentLoaded', function () {
MetaTracking.init();
});
}
})(window, document);

View File

@ -641,13 +641,13 @@
}
if(!clientType) {
clientType = context.JK.clientType();
context.JK.clientType().then(resp => clientType = resp).catch(error => logger.error('Error fetching clientType', error));
}
if(!mode) {
mode = 'client'
if (context.jamClient && context.jamClient.getOperatingMode) {
mode = context.jamClient.getOperatingMode()
}
//if (context.jamClient && context.jamClient.getOperatingMode) {
context.jamClient.getOperatingMode().then(resp => mode = resp).catch(error => logger.error('Error fetching operatingMode', error));
//}
isLatencyTesterMode = mode == 'server';
}
@ -670,9 +670,11 @@
if (isClientMode()) {
var client_type = context.JK.clientType()
var client_type;
context.JK.clientType().then(resp => client_type = resp).catch(error => logger.error('Error fetching clientType', error));
var client_id = (gon.global.env == "development" ? $.cookie('client_id') : null)
var machine = context.jamClient.SessionGetMacHash()
var machine;
context.jamClient.SessionGetMacHash().then(resp => machine = resp).catch(error => logger.error('Error fetching machine', error));
if (machine) {
machine = machine.all
}
@ -927,7 +929,7 @@
}
// Callbacks from jamClient
if (context.jamClient !== undefined && context.jamClient.IsNativeClient()) {
if (context.JK.isQWebEngine) {
context.jamClient.SendP2PMessage.connect(server.sendP2PMessage);
if (context.jamClient.SendLogin) {

View File

@ -18,6 +18,7 @@
//= require modern/JamServer_copy
//= require fakeJamClient
//= require fakeJamClientProxy
//= require fakeJamClientMessages
//= require fakeJamClientRecordings

View File

@ -229,10 +229,10 @@
$testScoreVideo.removeClass('testing');
}
function postDiagnostic() {
async function postDiagnostic() {
rest.createDiagnostic({
type: 'NETWORK_TEST_RESULT',
data: {client_type: context.JK.clientType(), client_id: context.JK.JamServer.clientID, summary: testSummary}
data: {client_type: 'client', client_id: context.JK.JamServer.clientID, summary: testSummary}
});
}
@ -249,8 +249,8 @@
return lastNetworkFailure;
}
function haltScoring() {
context.jamClient.SetLatencyTestBlocked(true)
async function haltScoring() {
await context.jamClient.SetLatencyTestBlocked(true)
rest.updateNetworkTesting({client_id: app.clientId, is_network_testing: true})
.fail(function(jqXHR) {
@ -264,8 +264,8 @@
})
}
function resumeScoring() {
context.jamClient.SetLatencyTestBlocked(false)
async function resumeScoring() {
await context.jamClient.SetLatencyTestBlocked(false)
rest.updateNetworkTesting({client_id: app.clientId, is_network_testing: false})
.fail(function(jqXHR) {
if(jqXHR.status == 404) {
@ -284,7 +284,7 @@
}
}
function testFinishedAudio() {
async function testFinishedAudio() {
var attempt = getCurrentAttemptAudio();
if (!testSummary.final) {
@ -302,13 +302,13 @@
}
// context.jamClient.GetNetworkTestScore() == 0 is a rough approximation if the user has passed the FTUE before
if (inGearWizard || context.jamClient.GetNetworkTestScore() == 0) {
if (inGearWizard || await context.jamClient.GetNetworkTestScore() == 0) {
trackedPass = true;
lastNetworkFailure = null;
context.JK.GA.trackNetworkTest(context.JK.detectOS(), testSummary.final.num_clients);
}
context.jamClient.SetNetworkTestScore(attempt.num_clients);
await context.jamClient.SetNetworkTestScore(attempt.num_clients);
if (testSummary.final.num_clients == 2) {
$testScoreAudio.addClass('acceptable');
}
@ -318,12 +318,12 @@
success = true;
}
else if (reason == "minimum_client_threshold") {
context.jamClient.SetNetworkTestScore(0);
await context.jamClient.SetNetworkTestScore(0);
renderStopTestAudio('', "We're sorry, but your router and Internet service will not effectively support JamKazam sessions. Please click the HELP button for more information.")
storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.bandwidth, avgBandwidth(attempt.num_clients - 1));
}
else if (reason == "unreachable" || reason == "no-transmit") {
context.jamClient.SetNetworkTestScore(0);
await context.jamClient.SetNetworkTestScore(0);
// https://jamkazam.atlassian.net/browse/VRFS-2323
renderStopTestAudio('', "We're sorry, but your router will not support JamKazam in its current configuration. Please click <a rel='external' href='https://jamkazam.desk.com/customer/portal/articles/1716139-what-to-do-if-you-cannot-pass-the-network-test'>HERE</a> for more information.");
storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.stun, attempt.num_clients);
@ -415,7 +415,7 @@
}
}
function testFinishedVideo() {
async function testFinishedVideo() {
var attempt = getCurrentAttemptVideo();
@ -440,13 +440,13 @@
}
// context.jamClient.GetNetworkTestScore() == 0 is a rough approximation if the user has passed the FTUE before
if (inGearWizard || context.jamClient.GetVideoNetworkTestScore() == 0) {
if (inGearWizard || await context.jamClient.GetVideoNetworkTestScore() == 0) {
//trackedPass = true;
//lastNetworkFailure = null;
//context.JK.GA.trackNetworkTest(context.JK.detectOS(), testSummary.final.num_clients);
}
context.jamClient.SetVideoNetworkTestScore(attempt.num_clients);
await context.jamClient.SetVideoNetworkTestScore(attempt.num_clients);
if (!testSummary.video_final.num_clients) {
$testScoreVideo.addClass('acceptable');
}
@ -459,12 +459,12 @@
success = true;
}
else if (reason == "minimum_client_threshold") {
context.jamClient.SetVideoNetworkTestScore(testSummary.video_final.num_clients - 1);
await context.jamClient.SetVideoNetworkTestScore(testSummary.video_final.num_clients - 1);
renderStopTestVideo(testSummary.video_final.num_clients - 1, reason)
//storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.bandwidth, avgBandwidth(attempt.num_clients - 1));
}
else if (reason == "unreachable" || reason == "no-transmit") {
context.jamClient.SetVideoNetworkTestScore(testSummary.video_final.num_clients - 1);
await context.jamClient.SetVideoNetworkTestScore(testSummary.video_final.num_clients - 1);
// https://jamkazam.atlassian.net/browse/VRFS-2323
renderStopTestVideo(testSummary.video_final.num_clients - 1, reason);
// storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.stun, attempt.num_clients);
@ -664,7 +664,7 @@
}, (gon.ftue_network_test_duration + 5) * 1000);
}
function attemptTestPassAudio() {
async function attemptTestPassAudio() {
var attempt = {};
attempt.payload_size = AUDIO_PAYLOAD_SIZE;
@ -687,14 +687,14 @@
audioScoring = true;
logger.debug("network test attempt: " + numClientToTestAudio + "-person audio session, 400 packets/s, " + AUDIO_PAYLOAD_SIZE + " byte payload")
context.jamClient.TestNetworkPktBwRate(serverClientId, createSuccessCallbackName(false), createTimeoutCallbackName(false),
await context.jamClient.TestNetworkPktBwRate(serverClientId, createSuccessCallbackName(false), createTimeoutCallbackName(false),
NETWORK_TEST_TYPES.PktTest400LowLatency,
gon.ftue_network_test_duration,
numClientToTestAudio - 1,
AUDIO_PAYLOAD_SIZE, gon.global.ftue_network_test_backend_retries);
}
function attemptTestPassVideo() {
async function attemptTestPassVideo() {
var attempt = {};
attempt.payload_size = VIDEO_PAYLOAD_SIZE;
@ -715,7 +715,7 @@
setBackendGuard();
logger.debug("network test attempt: " + numClientToTestVideo + "-person video session, 400 packets/s, " + VIDEO_PAYLOAD_SIZE + " byte payload")
context.jamClient.TestNetworkPktBwRate(serverClientId, createSuccessCallbackName(false), createTimeoutCallbackName(false),
await context.jamClient.TestNetworkPktBwRate(serverClientId, createSuccessCallbackName(false), createTimeoutCallbackName(false),
NETWORK_TEST_TYPES.PktTest400LowLatency,
gon.ftue_network_test_duration,
numClientToTestVideo - 1,
@ -723,13 +723,13 @@
}
// you have to score a little to 'prime' the logic to know whether it's on wireless or not
function primePump() {
async function primePump() {
audioScoring = true;
primeDeferred = new $.Deferred();
setPrimeGuard();
context.jamClient.TestNetworkPktBwRate(serverClientId, createSuccessCallbackName(true), createTimeoutCallbackName(true),
await context.jamClient.TestNetworkPktBwRate(serverClientId, createSuccessCallbackName(true), createTimeoutCallbackName(true),
NETWORK_TEST_TYPES.PktTest400LowLatency,
PRIME_PUMP_TIME,
2,
@ -746,9 +746,9 @@
$self.triggerHandler(NETWORK_TEST_CANCEL)
}
function postPumpRun() {
async function postPumpRun() {
// check if on Wifi 1st
var isWireless = context.jamClient.IsMyNetworkWireless();
var isWireless = await context.jamClient.IsMyNetworkWireless();
if (isWireless == -1) {
logger.warn("unable to determine if the user is on wireless or not for network test. skipping prompt.")
}
@ -773,8 +773,8 @@
}
}
function pauseForRecentScoresTime() {
var lastScoreTimes = context.jamClient.GetLastLatencyTestTimes()
async function pauseForRecentScoresTime() {
var lastScoreTimes = await context.jamClient.GetLastLatencyTestTimes()
console.log(lastScoreTimes)
@ -1271,7 +1271,7 @@
}
}
function initialize(_$step, _inGearWizard) {
async function initialize(_$step, _inGearWizard) {
$step = _$step;
inGearWizard = _inGearWizard;
@ -1320,7 +1320,7 @@
}).show();
}
operatingSystem = context.JK.GetOSAsString();
operatingSystem = await context.JK.GetOSAsString();
initializeVideoWatchButton();

View File

@ -253,7 +253,7 @@
currentNotificationPage++;
}
function initializeActions(payload, type) {
async function initializeActions(payload, type) {
var $notification = $('li[notification-id=' + payload.notification_id + ']');
var $btnNotificationAction = '#btn-notification-action';
@ -393,13 +393,13 @@
else if (type === context.JK.MessageType.RECORDING_MASTER_MIX_COMPLETE) {
$notification.find('#div-actions').hide();
logger.debug("context.jamClient.OnDownloadAvailable!")
context.jamClient.OnDownloadAvailable(); // poke backend, letting it know a download is available
await context.jamClient.OnDownloadAvailable(); // poke backend, letting it know a download is available
}
else if (type === context.JK.MessageType.JAM_TRACK_SIGN_COMPLETE) {
$notification.find('#div-actions').hide();
logger.debug("context.jamClient.OnDownloadAvailable!")
context.jamClient.OnDownloadAvailable(); // poke backend, letting it know a download is available
await context.jamClient.OnDownloadAvailable(); // poke backend, letting it know a download is available
}
else if (type === context.JK.MessageType.BAND_INVITATION) {
@ -592,7 +592,7 @@
function registerJoinRequest() {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST, function(header, payload) {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST, async function(header, payload) {
logger.debug("Handling JOIN_REQUEST msg " + JSON.stringify(payload));
handleNotification(payload, header.type);

View File

@ -41,9 +41,9 @@
var working = paginator.data('working');
if(!working) {
paginator.data('working', true);
onPageSelected(targetPage)
.done(function(data, textStatus, jqXHR) {
.then(function(data, textStatus, jqXHR) {
totalEntries = data.total_entries || parseInt(jqXHR.getResponseHeader('total-entries'));
pages = calculatePages(totalEntries, perPage);
options = { pages: pages,
@ -54,8 +54,10 @@
registerEvents(newPaginator);
paginator.replaceWith(newPaginator);
paginator = newPaginator;
paginator.data('working', false);
})
.always(function() {
.catch(function(err){
paginator.data('working', false);
});
}

View File

@ -303,7 +303,7 @@
}
}
function monitorRecordingPlayback() {
async function monitorRecordingPlayback() {
if (!monitoring) {
return;
}
@ -312,10 +312,10 @@
}
else {
if (playbackMonitorMode == PLAYBACK_MONITOR_MODE.JAMTRACK) {
var positionMs = context.jamClient.SessionCurrrentJamTrackPlayPosMs();
var duration = context.jamClient.SessionGetJamTracksPlayDurationMs();
var positionMs = await context.jamClient.SessionCurrrentJamTrackPlayPosMs();
var duration = await context.jamClient.SessionGetJamTracksPlayDurationMs();
var durationMs = duration.media_len;
var isPlaying = context.jamClient.isSessionTrackPlaying();
var isPlaying = await context.jamClient.isSessionTrackPlaying();
}
else if(playbackMonitorMode == PLAYBACK_MONITOR_MODE.BROWSER_MEDIA) {
var positionMs = BrowserMediaStore.onGetPlayPosition() || 0
@ -323,9 +323,9 @@
var isPlaying = BrowserMediaStore.playing;
}
else {
var positionMs = context.jamClient.SessionCurrrentPlayPosMs();
var durationMs = context.jamClient.SessionGetTracksPlayDurationMs();
var isPlaying = context.jamClient.isSessionTrackPlaying();
var positionMs = await context.jamClient.SessionCurrrentPlayPosMs();
var durationMs = await context.jamClient.SessionGetTracksPlayDurationMs();
var isPlaying = await context.jamClient.isSessionTrackPlaying();
}
executeMonitor(positionMs, durationMs, isPlaying)

View File

@ -0,0 +1,430 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebChannel module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
"use strict";
var QWebChannelMessageTypes = {
signal: 1,
propertyUpdate: 2,
init: 3,
idle: 4,
debug: 5,
invokeMethod: 6,
connectToSignal: 7,
disconnectFromSignal: 8,
setProperty: 9,
response: 10,
};
var QWebChannel = function(transport, initCallback)
{
if (typeof transport !== "object" || typeof transport.send !== "function") {
console.error("The QWebChannel expects a transport object with a send function and onmessage callback property." +
" Given is: transport: " + typeof(transport) + ", transport.send: " + typeof(transport.send));
return;
}
var channel = this;
this.transport = transport;
this.send = function(data)
{
if (typeof(data) !== "string") {
data = JSON.stringify(data);
}
channel.transport.send(data);
}
this.transport.onmessage = function(message)
{
var data = message.data;
if (typeof data === "string") {
data = JSON.parse(data);
}
switch (data.type) {
case QWebChannelMessageTypes.signal:
channel.handleSignal(data);
break;
case QWebChannelMessageTypes.response:
channel.handleResponse(data);
break;
case QWebChannelMessageTypes.propertyUpdate:
channel.handlePropertyUpdate(data);
break;
default:
console.error("invalid message received:", message.data);
break;
}
}
this.execCallbacks = {};
this.execId = 0;
this.exec = function(data, callback)
{
if (!callback) {
// if no callback is given, send directly
channel.send(data);
return;
}
if (channel.execId === Number.MAX_VALUE) {
// wrap
channel.execId = Number.MIN_VALUE;
}
if (data.hasOwnProperty("id")) {
console.error("Cannot exec message with property id: " + JSON.stringify(data));
return;
}
data.id = channel.execId++;
channel.execCallbacks[data.id] = callback;
channel.send(data);
};
this.objects = {};
this.handleSignal = function(message)
{
var object = channel.objects[message.object];
if (object) {
object.signalEmitted(message.signal, message.args);
} else {
console.warn("Unhandled signal: " + message.object + "::" + message.signal);
}
}
this.handleResponse = function(message)
{
if (!message.hasOwnProperty("id")) {
console.error("Invalid response message received: ", JSON.stringify(message));
return;
}
channel.execCallbacks[message.id](message.data);
delete channel.execCallbacks[message.id];
}
this.handlePropertyUpdate = function(message)
{
for (var i in message.data) {
var data = message.data[i];
var object = channel.objects[data.object];
if (object) {
object.propertyUpdate(data.signals, data.properties);
} else {
console.warn("Unhandled property update: " + data.object + "::" + data.signal);
}
}
channel.exec({type: QWebChannelMessageTypes.idle});
}
this.debug = function(message)
{
channel.send({type: QWebChannelMessageTypes.debug, data: message});
};
channel.exec({type: QWebChannelMessageTypes.init}, function(data) {
for (var objectName in data) {
var object = new QObject(objectName, data[objectName], channel);
}
// now unwrap properties, which might reference other registered objects
for (var objectName in channel.objects) {
channel.objects[objectName].unwrapProperties();
}
if (initCallback) {
initCallback(channel);
}
channel.exec({type: QWebChannelMessageTypes.idle});
});
};
function QObject(name, data, webChannel)
{
this.__id__ = name;
webChannel.objects[name] = this;
// List of callbacks that get invoked upon signal emission
this.__objectSignals__ = {};
// Cache of all properties, updated when a notify signal is emitted
this.__propertyCache__ = {};
var object = this;
// ----------------------------------------------------------------------
this.unwrapQObject = function(response)
{
if (response instanceof Array) {
// support list of objects
var ret = new Array(response.length);
for (var i = 0; i < response.length; ++i) {
ret[i] = object.unwrapQObject(response[i]);
}
return ret;
}
if (!response
|| !response["__QObject*__"]
|| response.id === undefined) {
return response;
}
var objectId = response.id;
if (webChannel.objects[objectId])
return webChannel.objects[objectId];
if (!response.data) {
console.error("Cannot unwrap unknown QObject " + objectId + " without data.");
return;
}
var qObject = new QObject( objectId, response.data, webChannel );
qObject.destroyed.connect(function() {
if (webChannel.objects[objectId] === qObject) {
delete webChannel.objects[objectId];
// reset the now deleted QObject to an empty {} object
// just assigning {} though would not have the desired effect, but the
// below also ensures all external references will see the empty map
// NOTE: this detour is necessary to workaround QTBUG-40021
var propertyNames = [];
for (var propertyName in qObject) {
propertyNames.push(propertyName);
}
for (var idx in propertyNames) {
delete qObject[propertyNames[idx]];
}
}
});
// here we are already initialized, and thus must directly unwrap the properties
qObject.unwrapProperties();
return qObject;
}
this.unwrapProperties = function()
{
for (var propertyIdx in object.__propertyCache__) {
object.__propertyCache__[propertyIdx] = object.unwrapQObject(object.__propertyCache__[propertyIdx]);
}
}
function addSignal(signalData, isPropertyNotifySignal)
{
var signalName = signalData[0];
var signalIndex = signalData[1];
object[signalName] = {
connect: function(callback) {
if (typeof(callback) !== "function") {
console.error("Bad callback given to connect to signal " + signalName);
return;
}
object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || [];
object.__objectSignals__[signalIndex].push(callback);
if (!isPropertyNotifySignal && signalName !== "destroyed") {
// only required for "pure" signals, handled separately for properties in propertyUpdate
// also note that we always get notified about the destroyed signal
webChannel.exec({
type: QWebChannelMessageTypes.connectToSignal,
object: object.__id__,
signal: signalIndex
});
}
},
disconnect: function(callback) {
if (typeof(callback) !== "function") {
console.error("Bad callback given to disconnect from signal " + signalName);
return;
}
object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || [];
var idx = object.__objectSignals__[signalIndex].indexOf(callback);
if (idx === -1) {
console.error("Cannot find connection of signal " + signalName + " to " + callback.name);
return;
}
object.__objectSignals__[signalIndex].splice(idx, 1);
if (!isPropertyNotifySignal && object.__objectSignals__[signalIndex].length === 0) {
// only required for "pure" signals, handled separately for properties in propertyUpdate
webChannel.exec({
type: QWebChannelMessageTypes.disconnectFromSignal,
object: object.__id__,
signal: signalIndex
});
}
}
};
}
/**
* Invokes all callbacks for the given signalname. Also works for property notify callbacks.
*/
function invokeSignalCallbacks(signalName, signalArgs)
{
var connections = object.__objectSignals__[signalName];
if (connections) {
connections.forEach(function(callback) {
callback.apply(callback, signalArgs);
});
}
}
this.propertyUpdate = function(signals, propertyMap)
{
// update property cache
for (var propertyIndex in propertyMap) {
var propertyValue = propertyMap[propertyIndex];
object.__propertyCache__[propertyIndex] = propertyValue;
}
for (var signalName in signals) {
// Invoke all callbacks, as signalEmitted() does not. This ensures the
// property cache is updated before the callbacks are invoked.
invokeSignalCallbacks(signalName, signals[signalName]);
}
}
this.signalEmitted = function(signalName, signalArgs)
{
invokeSignalCallbacks(signalName, signalArgs);
}
function addMethod(methodData)
{
var methodName = methodData[0];
var methodIdx = methodData[1];
object[methodName] = function() {
var args = [];
var callback;
for (var i = 0; i < arguments.length; ++i) {
if (typeof arguments[i] === "function")
callback = arguments[i];
else
args.push(arguments[i]);
}
webChannel.exec({
"type": QWebChannelMessageTypes.invokeMethod,
"object": object.__id__,
"method": methodIdx,
"args": args
}, function(response) {
if (response !== undefined) {
var result = object.unwrapQObject(response);
if (callback) {
(callback)(result);
}
}
});
};
}
function bindGetterSetter(propertyInfo)
{
var propertyIndex = propertyInfo[0];
var propertyName = propertyInfo[1];
var notifySignalData = propertyInfo[2];
// initialize property cache with current value
// NOTE: if this is an object, it is not directly unwrapped as it might
// reference other QObject that we do not know yet
object.__propertyCache__[propertyIndex] = propertyInfo[3];
if (notifySignalData) {
if (notifySignalData[0] === 1) {
// signal name is optimized away, reconstruct the actual name
notifySignalData[0] = propertyName + "Changed";
}
addSignal(notifySignalData, true);
}
Object.defineProperty(object, propertyName, {
configurable: true,
get: function () {
var propertyValue = object.__propertyCache__[propertyIndex];
if (propertyValue === undefined) {
// This shouldn't happen
console.warn("Undefined value in property cache for property \"" + propertyName + "\" in object " + object.__id__);
}
return propertyValue;
},
set: function(value) {
if (value === undefined) {
console.warn("Property setter for " + propertyName + " called with undefined value!");
return;
}
object.__propertyCache__[propertyIndex] = value;
webChannel.exec({
"type": QWebChannelMessageTypes.setProperty,
"object": object.__id__,
"property": propertyIndex,
"value": value
});
}
});
}
// ----------------------------------------------------------------------
data.methods.forEach(addMethod);
data.properties.forEach(bindGetterSetter);
data.signals.forEach(function(signal) { addSignal(signal, false); });
for (var name in data.enums) {
object[name] = data.enums[name];
}
}
//required for use with nodejs
if (typeof module === 'object') {
module.exports = {
QWebChannel: QWebChannel
};
}

View File

@ -32,7 +32,7 @@ profileUtils = context.JK.ProfileUtils
@root = $(@getDOMNode())
componentDidUpdate: () ->
datePicked = @datePicked.bind(this)
datePicked = @datePicked
@sessionDate = @root.find('.date-picker')
@sessionDate.each(() ->
$this = $(this)

View File

@ -537,7 +537,7 @@ profileUtils = context.JK.ProfileUtils
context.JK.popExternalLink("/client#/account/paymentHistory", true)
paymentMethod: () ->
if context.jamClient.IsNativeClient()
if context.JK.isQWebEngine
return `<div>
<div classNames="column column-left">
<p>Updating payment is only supported in a web browser. Please click the button below to open this page in your system web browser.</p>

View File

@ -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] || []

Some files were not shown because too many files have changed in this diff Show More