Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Stop all SFX

Is there a command or API script that provides a command to stop all music / sfx currently being played by the Jukebox? (Can you possibly do it with !sfx?)
1532735046

Edited 1532735128
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Roll20AM, as is the usual answer ;)
Scott C. said: Roll20AM, as is the usual answer ;) I'm not looking to replace my current scripts at the moment unfortunately. I'm just looking for a single tool not the whole toolbox if that makes sense.
1532755685
Victor B.
Pro
Sheet Author
API Scripter
Haven't tested this.  But here's how.... _.each(findObjs({type:'jukeboxtrack'}),(track)=>{     if (track.playing){         track.set({playing:false,softstop:true,loop:false});     } });
1532765439

Edited 1532766815
MyRoll20Stuffs
API Scripter
Thanks a lot for the quick reply with a viable solution. Unfortunately my campaign is so massive (Spread across 5 games so far) and my 2 scripts for using &amp; manipulating sfx / music / ambience / playlists is so heavily integrated into my game (I play SFX for every attack made, spell cast, action taken) that it would be a monumental task to switch over to something new at this point. Thanks Victor that did the trick. The only problem is for some reason if (track.playing) was not filtering out currently playing Jukebox objects and stopping them. I removed if (track.playing) and just brute force try to stop all tracks playing. This doesn't work for playlists though and in the API documentation it says to use the function stopJukeboxPlaylist(); - The combination of what you provided and that playlist function stops all tracks now. var ucaseContent = msg.content.toUpperCase(); /* "!sfx stopall" instantly stops all playlists and sound effects */ if (ucaseContent.indexOf('STOPALL') !== -1) { _.each(findObjs({type:'jukeboxtrack'}),(track)=&gt;{ track.set({playing:false,softstop:true,loop:false}); }); stopJukeboxPlaylist(); } Now I can just run !sfx stopall and all tracks / playlist of tracks instantly stops playing. I can clean up a lot of token action macros on certain NPCs now since I don't need to specify a particular track to stop before playing a new track. /* !SFX - Taken over by Kastion <a href="https://app.roll20.net/users/3173313/kastion" rel="nofollow">https://app.roll20.net/users/3173313/kastion</a> Last Edited July 28th 2018 */ state.SfxControl = state.SfxControl || {}; var SfxCtrl = {}; //customize options SfxCtrl.Command = '!SFX'; SfxCtrl.OptionDelimiter = ':'; SfxCtrl.PrefixDelimiter = '-'; SfxCtrl.SendAs = 'SFX'; SfxCtrl.VolumeBar = 'bar3_value'; SfxCtrl.AllowPlayerControl = true; on('chat:message', function(msg) { //validate command var param = msg.content.split(' '); var isGM = playerIsGM(msg.playerid); if(msg.type != 'api' || param[0].toLowerCase() != SfxCtrl.Command.toLowerCase() || (!isGM &amp;&amp; !SfxCtrl.AllowPlayerControl)) return; var replyTo = '/w "' + msg.who + '" '; var ucaseContent = msg.content.toUpperCase(); /* "!sfx stopall" instantly stops all playlists and sound effects */ if (ucaseContent.indexOf('STOPALL') !== -1) { _.each(findObjs({type:'jukeboxtrack'}),(track)=&gt;{ track.set({playing:false,softstop:true,loop:false}); }); stopJukeboxPlaylist(); } //can't have song: and list: parameters in the same command if(ucaseContent.indexOf(' SONG:') !== -1 &amp;&amp; ucaseContent.indexOf(' LIST:') !== -1) { sendChat(SfxCtrl.SendAs, replyTo + 'Error: SONG and LIST are exclusive options.'); return; } //set default options var play = true; var unique = false; var loop = false; var prefix = ''; var song = ''; var list = ''; var lasttype = ''; var vol = null; //define lookup tables function ReadParam(key) { params = { 'ACTION': function ReadAction(key) { actions = { 'PLAY': function() { play=true; loop=false; }, 'LOOP': function() { play=true; loop=true; }, 'STOP': function() { play=false; loop=false; }, 'DEFAULT': function() { errmsg = 'Unknown action: ' + key; }, }; (actions[key.toUpperCase()] || actions['DEFAULT'])(); }, 'UNIQUE': function(val) { unique = (val.toLowerCase() === 'true'); }, 'SONG': function(val) { song = val; lasttype = 'SONG'; }, 'LIST': function(val) { list = val; lasttype = 'LIST'; }, 'VOLUME': function(val) { if (!isNaN(val)) { vol = parseInt(Math.max(0,Math.min(100,val))); } }, 'DEFAULT': function() { errmsg = 'Unknown parameter: ' + key; }, }; return (params[key.toUpperCase()] || params['DEFAULT']); } //loop through each parameter for (i=1; i&lt;param.length; i++) { var errmsg; //split each parameter by the defined delimiter var opt = param[i].split(SfxCtrl.OptionDelimiter); switch (opt.length) { case 1: //if no delimiter was found, append the parameter to the song or list title if (lasttype === 'LIST') { list += ' ' + opt[0]; } else { song += ' ' + opt[0]; } break; case 2: //if one delimiter was found, filter through lookup tables ReadParam(opt[0])(opt[1]); break; default: //if more than one delimiter was found, set the error message errmsg = 'Too many delimiters in parameter: ' + param[i]; break; } //if an error msg was set, whisper and return if (errmsg) { sendChat(SfxCtrl.SendAs, replyTo + errmsg); return; } } //switch based on the the title entered switch(lasttype) { case 'LIST': if (!isGM) return; var ListID; var folders = JSON.parse(Campaign().get('_jukeboxfolder')); for (p in folders) { if(folders[p]['n'] &amp;&amp; folders[p]['n'] === list) { ListID = folders[p]['id']; } } if (ListID) { if (play) { playJukeboxPlaylist(ListID); } else { stopJukeboxPlaylist(); } } else { sendChat(SfxCtrl.SendAs, replyTo + 'Playlist Not Found: ' + list); } return; break; default: if (song == '' || !findObjs({ _type: 'jukeboxtrack', title: song })[0]) { sendChat(SfxCtrl.SendAs, replyTo + 'Song Not Found: ' + song); return; }; //create list of all campaign tracks var allsongs = findObjs({ _type: 'jukeboxtrack', }); //if unique, get the song prefix by delimiter as defined if (unique) { prefix = song.split(SfxCtrl.PrefixDelimiter); if (prefix.length == 1) { prefix = ''; } else { prefix = prefix[0]; } } //loop through each track in campaign jukebox _.each(allsongs, function(track) { //get the ID of the last person who played the song, if it's still playing var isPlaying = track.get('playing') &amp;&amp; (!track.get('softstop') || track.get('loop')); var playedbyid = isPlaying ? (state.SfxControl[track.get('_id')] || '') : ''; //turn off an active track if unique and the prefix matches if (unique &amp;&amp; play &amp;&amp; track.get('title') != song &amp;&amp; track.get('title').split(SfxCtrl.PrefixDelimiter)[0] == prefix &amp;&amp; track.get('playing') === true &amp;&amp; (isGM || playedbyid === msg.playerid )) { track.set({ playing: false, softstop: false, }); delete state.SfxControl[track.get('_id')]; } //if the song titles match, apply the settings if (track.get('title') == song) { if (isGM || !isPlaying || (isPlaying &amp;&amp; playedbyid === msg.playerid)) { track.set({ 'playing' : play, 'softstop' : false, 'loop' : (isGM) ? loop : false, 'volume' : !isNaN(vol) ? vol : track.get('volume'), }); if (play) { state.SfxControl[track.get('_id')] = msg.playerid; } else { delete state.SfxControl[track.get('_id')]; } } } }); break; } }); on('change:graphic', function(obj, old) { if(obj.get(SfxCtrl.VolumeBar) !== old[SfxCtrl.VolumeBar] &amp;&amp; !isNaN(obj.get(SfxCtrl.VolumeBar))) { var song = findObjs({ _type: 'jukeboxtrack', title: obj.get('name'), playing: true, })[0]; if (song) { song.set({ volume: parseInt(Math.min(Math.max(0,obj.get(SfxCtrl.VolumeBar)),100)), }); } } }); on('ready', function() { log("-=&gt; SFX Script loaded: Music Control for Tokens &lt;=- [Last Edited by Kastion July 28th 2018]"); }); Thanks a lot for your help guys. I really appreciate! These forums have one of he most positive and helpful communities I've ever come across on the net. Thanks again!