source: gs3-installations/mars/trunk/sites/mars/collect/amc-essentia/js/av_document.js@ 37029

Last change on this file since 37029 was 37029, checked in by davidb, 17 months ago

Some debugging work around treatment of AV values; Some initial work in moving the AV-chart to a main central area, rather than being part of the AV-Recommendation area

File size: 15.2 KB
Line 
1var AMC_SONG_DURATION = 30;
2
3var currentPosIsZero = true;
4var currentPosRunup = 0;
5
6
7function AVEnsurePaused()
8{
9 if (!wavesurfer.backend.isPaused()) {
10 $('#ws-pause-icon').hide();
11 $('#ws-play-icon' ).show();
12 $('#ws-playpause-label').html("Play");
13 }
14
15 wavesurfer.pause();
16}
17
18function AVPlay()
19{
20 $('#ws-play-icon' ).hide();
21 $('#ws-pause-icon').show();
22 $('#ws-playpause-label').html("Pause");
23
24 if (currentPosRunup>0) {
25 var skip_amount = -1 * currentPosRunup;
26 wavesurfer.skip(skip_amount);
27 currentPosRunup = 0;
28 }
29
30 wavesurfer.play();
31
32}
33
34function AVPlayPause()
35{
36 if (wavesurfer.backend.isPaused()) {
37 AVPlay();
38 }
39 else {
40 AVEnsurePaused();
41 }
42
43 //return wavesurfer.backend.isPaused() ? wavesurfer.play() : wavesurfer.pause();
44}
45
46function AVSeekTo(progressPos)
47{
48 wavesurfer.seekTo(progressPos);
49
50 if (progressPos == 0) {
51 recommendFromStart();
52 }
53}
54
55
56
57/*
58 function playFromOffset(id,frameOffset)
59 {
60 var msecOffset = 250 * frameOffset;
61 idElem = document.getElementById(id);
62 pagePlayer.handleClick({target:idElem}); // fake a click
63 soundManager.stopAll();
64 // soundManager.setPosition(id,5000);
65 soundManager.play(id,{position: msecOffset});
66 }
67 */
68
69
70function displayClampedCurrentTimeAndAV()
71{
72 // Note, the Arousal and Valence feature window values used is:
73 // 6 secs + 50% overlap
74 // So the Weka computed AV values are spaced out:
75 // 6s, 9s, 12s, ...
76
77 // clamp to ensure >= 6.0 secs
78
79 var current_time = Math.max(6.0,wavesurfer.getCurrentTime());
80 var current_time_1dp = current_time.toFixed(1);
81
82 var arousal_val = parseFloat($('#arousal-val').text());
83 var valence_val = parseFloat($('#valence-val').text());
84
85 var arousal_val_str = (arousal_val>0) ? "+"+arousal_val : ""+arousal_val;
86 var valence_val_str = (valence_val>0) ? "+"+valence_val : ""+valence_val;
87
88 $('#makeRecommendationFrom-AV').html(`(@${current_time_1dp} secs: arousal = ${arousal_val_str}, valence = ${valence_val_str})`);
89
90 return current_time;
91}
92
93function preSubmit(form)
94{
95 // Note, the Arousal and Valence feature window values used is:
96 // 6 secs + 50% overlap
97 // So the Weka computed AV values are spaced out:
98 // 6s, 9s, 12s, ...
99
100 // clamp to ensure >= 6.0 secs
101 //var current_time = Math.max(6.0,wavesurfer.getCurrentTime());
102 //var current_time_1dp = current_time.toFixed(1);
103
104 var clamped_current_time = displayClampedCurrentTimeAndAV();
105
106 AVEnsurePaused();
107
108 weka_segment = Math.round(clamped_current_time/3) * 3;
109 form.elements["s1.offset"].value = weka_segment;
110
111 var arousal_val = parseFloat($('#arousal-val').text());
112 var valence_val = parseFloat($('#valence-val').text());
113
114 //$('#makeRecommendationFrom-AV').html(`(@${current_time_1dp} secs: arousal=${arousal_val}, valence=${valence_val})`);
115
116 return submitAVRecommendation(form, arousal_val,valence_val, clamped_current_time);
117}
118
119function AVPlotRecommendations()
120{
121 var $av_recommendations = $('.AVRecommendation');
122
123 var min_arousal_val = +1.0;
124 var max_arousal_val = -1.0;
125
126 var min_valence_val = +1.0;
127 var max_valence_val = -1.0;
128
129 $av_recommendations.each(function(index_unused) {
130 var arousal_val = $(this).data("arousalval");
131 var valence_val = $(this).data("valenceval");
132
133 if (arousal_val < min_arousal_val) {
134 min_arousal_val = arousal_val;
135 }
136 if (arousal_val > max_arousal_val) {
137 max_arousal_val = arousal_val;
138 }
139
140
141 if (valence_val < min_valence_val) {
142 min_valence_val = valence_val;
143 }
144 if (valence_val > max_valence_val) {
145 max_valence_val = valence_val;
146 }
147
148 });
149
150 console.log(`AVRecommendations Arousal limits: ${min_arousal_val} <-> ${max_arousal_val}`);
151 console.log(`AVRecommendations Valence limits: ${min_valence_val} <-> ${max_valence_val}`);
152
153 var av_cluster_x_org = (min_arousal_val + max_arousal_val)/2.0;
154 var av_cluster_y_org = (min_valence_val + max_valence_val)/2.0;
155
156 var av_cluster_x_delta = Math.abs(min_arousal_val - max_arousal_val)/2.0;
157 var av_cluster_y_delta = Math.abs(min_valence_val - max_valence_val)/2.0;
158
159 //var av_cluster_rad = Math.max(Math.max(av_cluster_x_delta,av_cluster_y_delta),3.0);
160
161 var av_cluster_rad = Math.max(av_cluster_x_delta,av_cluster_y_delta);
162 var disp_cluster_coord = av_to_display_coord(av_cluster_rad,av_cluster_rad);
163 var disp_cluster_rad = disp_cluster_coord.x - av_chart_disp_x_mid; // **** **** ????
164 var disp_cluster_rad_maxed = Math.max(disp_cluster_rad,3.0);
165
166 var disp_coord = av_to_display_coord(av_cluster_x_org,av_cluster_y_org);
167 var disp_x = disp_coord.x;
168 var disp_y = disp_coord.y;
169
170 var av_chart_canvas = document.getElementById('av-chart-canvas');
171
172 var ctx = av_chart_canvas.getContext("2d");
173 ctx.clearRect(0, 0, av_chart_canvas.width, av_chart_canvas.height);
174 ctx.beginPath();
175 ctx.arc(disp_x/2, disp_y/2, disp_cluster_rad_maxed/2, 0, 2*Math.PI, false);
176 ctx.fillStyle = 'rgba(50,50,128,0.5)';
177 ctx.fill();
178 ctx.lineWidth = 1;
179 ctx.strokeStyle = 'rgba(0,0,160,0.5)';
180 ctx.stroke();
181
182}
183
184function ajaxUpdateDocumentDisplayed()
185{
186 var $resultsTable = $('#resultsTable');
187
188 var $resultsTable_trs = $resultsTable.find('tr');
189
190 if ($resultsTable_trs.length>0) {
191 var $resultsTable_tr1 = $resultsTable_trs.first();
192 var div_doc_id = $resultsTable_tr1.attr('id')
193 var doc_id = div_doc_id.substring(3);
194
195 console.log("first AV recommendation doc id = " + doc_id);
196
197 var $av_recommendation = $resultsTable_tr1.find('.AVRecommendation').first();
198
199 var new_doc_url = $av_recommendation.attr('href');
200 var new_doc_url_parts = new_doc_url.split("#");
201
202 var new_doc_metadata_url = new_doc_url_parts[0] + "&excerptid=metadata-documenttext#" + new_doc_url_parts[1];
203 var new_doc_playervisual_url = new_doc_url_parts[0] + "&excerptid=playervisual-documenttext#" + new_doc_url_parts[1];
204
205 //console.log("new doc metadata url = " + new_doc_metadata_url);
206 //console.log("new doc playervisual url = " + new_doc_playervisual_url);
207
208
209 // current URL ends with collect/amc-essentia/document/ds_51017_15513?p.frameOffset=...
210 // Need to remove old '/document/ds_...' and replace with new doc
211
212 const current_doc_url_str = window.location.href;
213
214 console.log(current_doc_url_str);
215 var push_doc_url_str = current_doc_url_str.replace(/document\/\w+\?/,"document/"+doc_id+"?");
216 console.log("new doc url str = " + push_doc_url_str);
217 const push_doc_url = new URL(push_doc_url_str);
218
219 var frameOffset = $av_recommendation.data("frameoffset");
220 push_doc_url.searchParams.set('p.frameOffset', frameOffset);
221 push_doc_url.searchParams.set('d', doc_id);
222 window.history.pushState({}, '', push_doc_url);
223 //window.history.replaceState({}, '', push_doc_url);
224
225
226
227 $('#metadata-documenttext').css("cursor","wait");
228 $('#playervisual-documenttext').css("cursor","wait");
229
230 $.ajax({
231 method: "GET",
232 url: new_doc_metadata_url,
233 })
234 .always(function() {
235 $('#metadata-documenttext').css("cursor","revert");
236 })
237
238 .fail(function(jqXHR,textStatus) {
239 console.error( "metadata-documenttext ajax request failed: " + textStatus);
240 })
241 .done(function(html_result) {
242 $('#metadata-documenttext').replaceWith(html_result);
243 });
244
245
246 $.ajax({
247 method: "GET",
248 url: new_doc_playervisual_url,
249 })
250 .always(function() {
251 $('#playervisual-documenttext').css("cursor","revert");
252 })
253 .fail(function(jqXHR,textStatus) {
254 console.error( "playervisual-documenttext equest failed: " + textStatus);
255 })
256 .done(function(html_result) {
257
258 $('#playervisual-documenttext').replaceWith(html_result);
259
260 gs.cgiParams['p_frameOffset'] = frameOffset;
261 gs.documentMetadata["assocfilepath"] = $('#ajax-loaded-assocfilepath').text();
262
263 initPlayerVisual();
264 initWavesurferPlayer();
265
266 wavesurfer.seekTo(frameOffset/AMC_SONG_DURATION);
267
268 postInitWavesurfer(wavesurfer);
269
270
271 });
272
273
274 $resultsTable_tr1.slideUp();
275
276 //var arousal_val = $av_recommendation.data("arousalval");
277 //var valence_val = $av_recommendation.data("valenceval");
278
279
280 }
281
282}
283
284function submitAVRecommendation(form, arousal_val,valence_val, current_time)
285{
286 form.elements["s1.arousal"].value = arousal_val;
287 form.elements["s1.valence"].value = valence_val;
288
289 var args = {
290 "a": "q",
291 "rt": "rd",
292 "s": "AudioQuery",
293 "sa": "",
294 "c": gs.cgiParams["c"],
295 "q": gs.cgiParams["d"],
296 "s1.query": gs.cgiParams["d"],
297 "s1.maxDocs": form.elements["s1.maxDocs"].value,
298 "s1.hitsPerPage": form.elements["s1.hitsPerPage"].value,
299 "s1.offset": form.elements["s1.offset"].value,
300 "s1.length": form.elements["s1.length"].value,
301 "s1.arousal": arousal_val,
302 "s1.valence": valence_val,
303 "startPage": 1,
304 "excerptid": "resultsArea"
305 };
306
307
308 var url = "https://mars.so-we-must-think.space/greenstone3/library";
309
310 $('#recommendationArea').css("cursor","wait");
311 $('#resultsAreaDiv').slideDown();
312 $('#resultsAreaDiv').html("Retrieving recommendation ...");
313
314 $.ajax({
315 method: "GET",
316 url: url,
317 data: args
318 })
319 .always(function() {
320 $('#recommendationArea').css("cursor","revert");
321 })
322 .fail(function(jqXHR,textStatus) {
323 console.error( "Request failed: " + textStatus);
324 })
325 .done(function(html_result) {
326 $('#resultsAreaDiv').html("<div>Recommendations:</div>"+html_result);
327 $('#av-chart-div').show();
328
329 AVPlotRecommendations();
330
331 if (current_time) {
332 const updated_url = new URL(window.location);
333 updated_url.searchParams.set('p.frameOffset', current_time);
334 //window.history.pushState({}, '', url + "?p.frameOffset=" + current_time);
335 //window.history.pushState({}, '', updated_url);
336 window.history.replaceState({}, '', updated_url);
337 }
338 else {
339 // The result of a click on the AV-chart
340 ajaxUpdateDocumentDisplayed();
341 }
342 });
343
344 // stop submit
345 return false;
346
347 // force GET method request to go ahead
348 //return true;
349}
350
351
352
353function recommendFromStart()
354{
355 currentPosIsZero = true;
356 $('#makeRecommendationFrom').html("Based on the start of this musical/sound art work: ");
357}
358
359
360function recommendFromPos()
361{
362 currentPosIsZero = false;
363 $('#makeRecommendationFrom').html("Based on the current timeline position of this musical/sound art work: ");
364}
365
366
367
368function postInitWavesurfer(wavesurfer)
369{
370 console.log("postInitWavesurfer called with wavesufer = " + wavesurfer);
371
372 wavesurfer.load(gs.variables.mp3url);
373
374 wavesurfer.on('audioprocess', function () {
375 var current_time = wavesurfer.getCurrentTime();
376 var current_time_rounded = Math.round(current_time * 10) / 10
377 var current_time_rounded = current_time.toFixed(1);
378 $('#audioCurrentPos').html(current_time_rounded + " secs");
379
380 if (current_time == 0) {
381 recommendFromStart();
382 }
383 else if ((currentPosIsZero) && (current_time > 0)) {
384 recommendFromPos();
385 }
386 displayClampedCurrentTimeAndAV();
387 });
388
389 wavesurfer.on('ready', function () {
390
391 console.log("**** wavesurfer ready()");
392
393 if ('p_frameOffset' in gs.cgiParams) {
394 var frameOffset = gs.cgiParams['p_frameOffset'];
395 //console.log("**** starting play @ " + frameOffset);
396 //wavesurfer.play(frameOffset);
397 //console.log("**** setting play seek @ " + frameOffset);
398 wavesurfer.seekTo(frameOffset/AMC_SONG_DURATION);
399 recommendFromPos();
400 displayClampedCurrentTimeAndAV();
401
402 console.log("av_document.js: **** Keeping 'currentPosRunup' at 0 for now!");
403 /*if (frameOffset>1.0) {
404 currentPosRunup = 1.0; // 1 second
405 }*/
406 }
407 else {
408 recommendFromStart();
409 displayClampedCurrentTimeAndAV();
410 }
411 });
412
413}
414
415/*
416
417y-top: 146
418
419Centre: 412,443
420
421y-bot:735
422
423x-left: 120
424
425x-right 710
426
427
428Full image:
429 911 x 825 pxs
430
431
432
433 AV centre: 412,443
434
435delta x/y: from centre: 292 <-> 298
436-1 <-> 0 <-> +1
437 295 295
438
439
440SVG:
441
442 241 x 248
443 scaled
444 0.26458
445
446*/
447
448var av_chart_orig_r = 295;
449
450var av_chart_orig_x_org = 412;
451var av_chart_orig_y_org = 443;
452
453var av_chart_orig_x_dim = 911;
454var av_chart_orig_y_dim = 825;
455
456var av_chart_disp_x_dim = 300; // ****
457var av_chart_disp_x_mid = av_chart_disp_x_dim/2.0;
458
459var av_chart_scale = av_chart_orig_x_dim / av_chart_disp_x_dim;
460
461function display_to_av_coord(disp_x,disp_y)
462{
463 var scaled_disp_x = disp_x * av_chart_scale;
464 var scaled_disp_y = disp_y * av_chart_scale;
465
466 var orig_av_x = scaled_disp_x - av_chart_orig_x_org;
467 var orig_av_y = -1 * (scaled_disp_y - av_chart_orig_y_org); // flip y axis
468
469 var av_x = orig_av_x / av_chart_orig_r;
470 var av_y = orig_av_y / av_chart_orig_r;
471
472 var capped_av_x = Math.max(Math.min(av_x,1.0),-1.0);
473 var capped_av_y = Math.max(Math.min(av_y,1.0),-1.0);
474
475 return { "x": capped_av_x, "y": capped_av_y };
476}
477
478
479function av_to_display_coord(av_x,av_y)
480{
481 //var capped_av_x = Math.max(Math.min(av_x,1.0),-1.0);
482 //var capped_av_y = Math.max(Math.min(av_y,1.0),-1.0);
483
484 // transform the coord system from av [-1,1] to be the original SVG AV chart size
485 var orig_av_x = av_x * av_chart_orig_r;
486 var orig_av_y = av_y * av_chart_orig_r;
487
488 // tranform the coord system to be expressed from the top-left as the origin
489 var scaled_disp_x = orig_av_x + av_chart_orig_x_org;
490 var scaled_disp_y = (-1 * orig_av_y) + av_chart_orig_y_org;
491
492 var disp_x = scaled_disp_x / av_chart_scale;
493 var disp_y = scaled_disp_y / av_chart_scale;
494
495 return { "x": disp_x, "y": disp_y };
496}
497
498
499function av_chart_click(elem,e)
500{
501 var offset = $(elem).offset();
502
503 var elem_x_org = offset.left;
504 var elem_y_org = offset.top;
505
506 var disp_x = e.pageX - elem_x_org;
507 var disp_y = e.pageY - elem_y_org;
508
509 //console.log(`(disp_x,disp_y) = (${disp_x},${disp_y})`);
510 var av_coord = display_to_av_coord(disp_x,disp_y);
511 var capped_av_x = av_coord.x;
512 var capped_av_y = av_coord.y;
513
514 console.log(`av x,y: (${capped_av_x},${capped_av_y})`);
515
516 //var disp_coord = av_to_display_coord(capped_av_x,capped_av_y);
517 //var reconverted_disp_x = disp_coord.x;
518 //var reconverted_disp_y = disp_coord.y;
519
520 //console.log(`reconverted (disp_x,disp_y) = (${reconverted_disp_x},${reconverted_disp_y})`);
521
522 var form = $('#av-query-form')[0];
523
524 submitAVRecommendation(form, capped_av_x, capped_av_y, null);
525
526}
527
528function initPlayerVisual() {
529
530 const doc_url = new URL(window.location);
531 var renderWave = doc_url.searchParams.get('renderWave');
532
533 if (renderWave && (renderWave == 1)) {
534 // showing the waveform => offer link to spectrogram
535 const sts_url = new URL(window.location);
536 sts_url.searchParams.set('renderWave', 0);
537 $('#switch-to-spectrogram').attr("href",sts_url);
538 $('#switch-to-waveform').hide();
539
540 $('#av-timelinebar-help').hide();
541 }
542 else {
543 // show the spectrogram => offer link to waveform
544
545 const stw_url = new URL(window.location);
546 stw_url.searchParams.set('renderWave', 1);
547 $('#switch-to-waveform').attr("href",stw_url);
548 $('#switch-to-spectrogram').hide();
549
550 $('#av-timelinebar-help').show();
551 }
552}
553
554function showAVChart()
555{
556 $('#av-chart-outerdiv').slideDown();
557 $('#show-av-chart').hide();
558 $('#hide-av-chart').show();
559
560 return false;
561}
562
563function hideAVChart()
564{
565 $('#av-chart-outerdiv').slideUp();
566 $('#hide-av-chart').hide();
567 $('#show-av-chart').show();
568
569 return false;
570}
571
572$(document).ready(function() {
573
574 initPlayerVisual();
575
576 $('#av-chart-img').on("click",function(e) { av_chart_click(this,e) } );
577});
578
Note: See TracBrowser for help on using the repository browser.