How to Correctly Clean Up timbre.js - javascript

I am running Timbre.js successfully on iOS 9.2 by coupling it with AudioContextMonkeyPatch, and I am trying to use a slightly modified version of code found here: http://mohayonao.github.io/timbre.js/interval.html. The code (to save lookup) is:
var freqs = T(function(count) {
return [220, 440, 660, 880][count % 4];
});
var osc = T("sin", {freq:freqs, mul:0.5});
var env = T("perc", {a:50, r:500}, osc).bang();
var interval = T("param", {value:500}).linTo(50, "30sec");
T("interval", {interval:interval}, freqs, env).start();
env.play();
What I am trying to figure out is how to start and then stop and then re-start the sound. I'm trying to see how the developer's example 'Pause' button works, but I can't seem to locate that code example. I do basic things tike "T().stop(); env.pause();" followed by "env.play();" (in separate onClick events), and I end up with multiple signals on the second play event. Really frustrating. The documentation suggests a 'removeAll' will remove all items loaded into Timbre() (or T()?), but applying this in my stop function does not provide a satisfactory result either.
Anyone know the correct way to pause and restart this script snippet?

In order to start and stop the sequence you need to assign the last T function to a variable. You can then use .start() and .stop() as you like:
code....
var interval = T("param", {value:500}).linTo(50, "30sec");
var audioSequence = T("interval", {interval:interval}, freqs, env);
env.play();
audioSequence.start(); // Start the Sequence
interval.stop(); // Stop the interval
audioSequence.stop(); // Stop the Sequence
interval.start(); // Restart the Interval
audioSequence.start(); // Restart the Sequence
Its a little confusing at first as play()/pause() is used for oscillators or drums for example and start()/stop() is used for intervals.

Related

Set videoElement.currentTime in Hulu video player doesn't work, and breaks the player

I have a Chrome extension in which I'm trying to jump forward or backward (based on a user command) to a specific time in the video by setting the currentTime property of the video object. Before trying to set currentTime, a variety of operations work just fine. For example:
document.getElementsByTagName("video")[1].play(); // works fine
document.getElementsByTagName("video")[1].pause(); // works fine
document.getElementsByTagName("video")[1].muted = true; // works fine
document.getElementsByTagName("video")[1].muted = false; // works fine
BUT as soon as I try to jump to a specific point in the video by doing something like this:
document.getElementsByTagName("video")[1].currentTime = 500; // doesn't work
No errors are thrown, the video pauses, and any attempted actions after this point do nothing. So the items shown above (play/pause/mute/unmute) no longer work after attempting to set currentTime. If I read the value of currentTime after setting it, it correctly displays the new time that I just set it to. Yet nothing I do will make it play, and in fact even trying to make the video play by clicking the built-in toolbar no longer works. So, apparently setting currentTime wreaks all kinds of havoc in the video player. Yet if I reload the video, all works as before as long as I don't try to set currentTime.
I can easily jump to various times (backward or forward) by sliding the slider on the toolbar, so there must be some way internally to do that. Is there some way I can discover what code does a successful time jump? Because it's a Chrome extension I can inject custom js into the executing Hulu js, but I don't know what command I would send.
Any ideas?
Okay I fiddled around with it for a little while to see how I could reproduce the click event on the player and came up with the following solution:
handleViewer = function(){
var thumbnailMarker = $('.thumbnail-marker'),
progressBarTotal = thumbnailMarker.parent(),
controlsBar = $('.controls-bar'),
videoPlayer = $('#content-video-player');
var init = function(){
thumbnailMarker = $('.thumbnail-marker');
progressBarTotal = thumbnailMarker.parent();
controlsBar = $('.controls-bar');
videoPlayer = $('#content-video-player');
},
check = function(){
if(!thumbnailMarker || !thumbnailMarker.length){
init();
}
},
show = function(){
thumbnailMarker.show();
progressBarTotal.show();
controlsBar.show();
},
hide = function(){
controlsBar.hide();
},
getProgressBarWidth = function(){
return progressBarTotal[0].offsetWidth;
};
return {
goToTime: function(time){
var seekPercentage,
duration;
check();
duration = videoPlayer[0].duration;
if(time > 0 && time < duration){
seekPercentage = time/duration;
this.jumpToPercentage(seekPercentage);
}
},
jumpToPercentage: function(percentage){
check();
if(percentage >= 1 && percentage <= 100){
percentage = percentage/100;
}
if(percentage >= 0 && percentage < 1){
show();
thumbnailMarker[0].style.left = (getProgressBarWidth()*percentage)+"px";
thumbnailMarker[0].click();
hide();
}
}
}
}();
Once that code is initialized you can do the following:
handleViewer.goToTime(500);
Alternatively
handleViewer.jumpToPercentage(50);
I've tested this in chrome on a MacBook pro. Let me know if you run into any issues.
Rather than try to find the javascript responsible for changing the time, why not try to simulate the user events that cause the time to change?
Figure out the exact sequence of mouse events that trigger the time change.
This is probably some combination of mouseover, mousedown, mouseup, and click.
Then recreate those events synthetically and dispatch them to the appropriate elements.
This is the approach taken by extensions like Stream Keys and Vimium.
The video should be ready to play before setting the currentTime.
Try adding this line before setting currentTime?
document.getElementsByTagName("video")[1].play();
document.getElementsByTagName("video")[1].currentTime = 500;
Looks like it works if you first pause, then set currentTime, then play again.
document.getElementsByTagName("video")[1].pause()
document.getElementsByTagName("video")[1].currentTime = 800.000000
document.getElementsByTagName("video")[1].play()
Probably would need to hook into some event like onseeked to put in the play command to make it more robust.

Using Nightwatch for demo - slow down assertions by config

my team and me are using Nightwatch to write end-to-end-acceptance tests for a microservice oriented architecture with a total of five systems.
After putting in some work to set it up and wiring together our services with docker-compose, it works great now and all tests are clicked through on the UI in a browser (not headless).
We got the idea to use this for demos, too (initial sprint demo etc) and wondered if there is some kind of setting (which we didn't found until now) or other possibility to simple add some artificial delay between the clicks/tests/assertions and everything.
Does someone have an idea?
You can add pauses in your suite wherever you want by using:
.pause(5000) // a pause for 5 seconds
//or alternately
.pause(this.timeout)
this.timeout can be set in your base-test-case.js
var timeout = 5000; // in your variable declarations
and then in that same file, on your base Class prototype you want:
before: function (client) {
this.timeout = timeout;
browser.pause between clicks or setValue to have nice delay, anything between 100-300 miliseconds is good
http://nightwatchjs.org/api#pause

Howler js pause/resume trouble

I'm using the Howler js library to set a player in an app running through Electron. First everything seemed to work well, but after a few weeks using the app, a bug occurs repeatedly, but not constantly : the pause() function doesn't work. Here's some piece of code :
Initialization :
var is_paused = true;
var currentTrack = "track1";
var tracks = {"track1" : new Howl({urls: ['path/to/track1.mp3']}),
"track2" : new Howl({urls: ['path/to/track2.mp3']}),
"track3" : new Howl({urls: ['path/to/track3.mp3']})
};
Then I have a few buttons for play/resume, pause, stop, and play a specific track :
$('#playS').click(function(){
if (is_paused){
tracks[currentTrack].play();
is_paused = false;
}
});
$('#pauseS').click(function(){
tracks[currentTrack].pause();
is_paused = true;
});
$('.trackBtn').click(function(){
tracks[currentTrack].stop();
currentTrack = $(this).attr('id');
tracks[currentTrack].play();
is_paused = false;
});
The problem is that sometimes (generally after 40-45 min of a track playing), the pause() function just do nothing, which is really annoying cause I need to pause the track and play another 30 sec file and then resume the current track. I checked the console while the bug occurs, it says absolutely nothing. I have no idea where the bug comes from, there's not a lot of information about how works the library. I really need some help here, thank's in advance.
EDIT : one more thing, when pause() doesn't work, if I click play() the track plays from the begining, and I have control on this second instance of the track. It's like the first instance has reached end, but still playing.
Without knowing what version of Howler you're using, or what other code might be messing things up, there is one thing I think might help: You don't need to track the paused state. The "playing" method takes care of that. I've made it work using something like this:
// If it's paused, it's not playing, so...
paused = !myHowlInstance.playing();
Another thing I noticed is that you have currentTrack = $(this).attr('id'); in your (I think it's a) stop button. Unfortunately I don't know JQuery well enough to know if there's anything wrong with that (I'm more of a Dojo fan myself). But it looks like currentTrack may be set to some value not in your list (which would break tracks[currentTrack]). You might want to go into the console and type tracks["track1"], currentTrack etc. to see their values. You can even do tracks[currentTrack].play(); and see what happens. I wasn't sure if you knew you could do that (it was a huge help to me when I found out about it).
And as far as the "un-pausing" starting from the beginning, I'm currently struggling with it myself; at this time there's no clear way to do this (no resume(), pause(false) etc.), and I've seen a few more questions on the subject on Google and SO, so you're not alone. I've experimented with the seek method, but with no luck. I'll post a comment if/when I reach a breakthrough on that. :)
EDIT: I figured out the play-from-beginning thing. It does involve "seek", and also the whole "instance ID" concept (which I never really understood the importance of from the documentation).
Here's an example from a project I'm working on (also a game); it doesn't involve JQuery (sorry), but it should give you the gist of how to fix the problem.
var myBgMusic = new Howl(...);
var myMusicID = myBgMusic.play(); // The docs say play() returns an ID, and I'll be passing that to "seek" later.
var paused = false;
var saveSeek;
function TogglePause() {
if (paused) {
myBgMusic.play(myMusicID);
myBgMusic.seek(saveSeek, myMusicID);
} else {
myBgMusic.pause();
saveSeek = myBgMusic.seek(myMusicID);
}
};

youtube repeat oneliner

I am trying to make a oneliner to repeat videos.
I started looking for that replay button to trigger another round:
$("[title='Replay']")[0].click();
A self calling function to loop in the background while the vid is running.
rpt=function(){setTimeout(function(){alert("blarg");rpt()},5000)}
putting those two things together and adding a tiny bit of fluff:
$ = jQuery to initialize shiny $()-syntax and finally rpt();to get things rolling:
$=jQuery,rpt=function(){setTimeout(function(){$("[title='Replay']")[0].click(),rpt()},100)};rpt();
alas, the parts work but not the whole thing
I noticed that the console is printing an error message if I enter the final line before the video has finished; since the button is not found yet and therefore a call to .click() on undefined isn't working.
Shouldn't the function still loop in the background and trigger during a later call, as soon as the replay button is there for jQuery to grab?
I'm using chrome 44.0.2403.130 and jQuery: 1.10.1
Add a verification to make sure there is a replay element available.
Use setInterval() instead of setTimeout().
By default (and unless you use other conflicting libraries), jQuery is assigned to the $ variable on its initialization.
setInterval(function(){if($("[title='Replay']").length)$("[title='Replay']").trigger('click');},100);
one line repeat + number of repeat appended in title:
var title=$('#eow-title').innerHTML; var replaysN = 1; setInterval(function(){if($('.ytp-play-button').title == 'Replay') {$('.ytp-play-button').click();$('#eow-title').innerHTML = title+' (x'+replaysN+')';replaysN++;} }, 1000);
..after some weeks after making this post, there was a new feature in youtube :D
After right-click on video -> Loop
So every customization is useless :)

Lengthening MIDI.js piano note duration

I'm using MIDI.js to build a music app that allows users to play piano through their keyboard.
Everything is working, but the problem I'm having is that the notes (called with MIDI.noteOn) only last 3 seconds, then just cut off. I'm trying to find a way to:
1- Make the note last for longer.
2- Make the note fade to nothing as opposed to just cutting off.
Could anyone point me in the right direction with there? There is so little documentation & discussion on MIDI.js.
Thanks in advance!
EDIT: The instrument name is acoustic_grand_piano
In theory, you need to call noteOff at the proper time.
In practice, MIDI.Plugin.js has this:
// FIX: needs some way to fade out smoothly..
root.noteOff = function (channel, note, delay) {
// var source = sources[channel+""+note];
// if (!source) return;
// source.noteOff(delay || 0);
// return source;
};

Categories