Skip to content

Commit

Permalink
new freesound result component to replace embedded iframes, reduces h…
Browse files Browse the repository at this point in the history
…ttp requests by an order of magnitude
  • Loading branch information
jmarcosfer committed Feb 3, 2022
1 parent 780cab9 commit 22bf4a7
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 20 deletions.
17 changes: 11 additions & 6 deletions examples/demos/onsets/src/components/BrowseDisplayPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,34 @@
<b-alert id="search-failure" show dismissible v-show="showSearchFailureBanner" @dismissed="showSearchFailureBanner = false; searchTerm=''">
Sorry, Freesound search failed. Try another search term or sound ID, or upload your own sound instead.
</b-alert>
<freesound-results :class="[{ 'd-flex': showFreesoundResults }, { 'd-none': !showFreesoundResults }]"></freesound-results>
<freesound-result-list v-if="showFreesoundResults" :class="[{ 'd-flex': showFreesoundResults }, { 'd-none': !showFreesoundResults }]"
:sounds="freesoundResults"></freesound-result-list>
<audio-display v-show="!showFreesoundResults"></audio-display>
</section>
</template>

<script>
import EventBus from '../core/event-bus';
import AudioDisplay from './AudioDisplay.vue';
import FreesoundResults from './FreesoundResults.vue';
import FreesoundResultList from './FreesoundResultList.vue';
import freesound from 'freesound';
import apiKey from '../.env/key';
export default {
components: { AudioDisplay, FreesoundResults },
components: { AudioDisplay, FreesoundResultList },
data () {
return {
showFreesoundResults: false,
freesoundResults: [],
searchTerm: "",
uploadLabel: null,
showSearchFailureBanner: false,
showNoResultsFoundBanner: false
}
},
methods: {
searchFreesound () {
searchFreesound (ev) {
this.$root.$emit('bv::hide::tooltip');
const isSearchById = /#\d+$/.test(this.searchTerm); // match regex for #<id_number>
if (isSearchById) {
freesound.getSound(this.searchTerm.split('#').pop(), this.handleSearchSuccess, this.handleSearchFailure);
Expand Down Expand Up @@ -97,7 +100,8 @@ export default {
handleSearchSuccess (sound) {
// guard: sound collection or single sound?
if (sound.results == undefined && 'id' in sound) { // deal with it as single sound (id search)
EventBus.$emit("successful-fs-search", [sound]);
// EventBus.$emit("successful-fs-search", [sound]);
this.freesoundResults = [sound];
this.showFreesoundResults = true;
return;
}
Expand All @@ -106,7 +110,8 @@ export default {
this.showNoResultsFoundBanner = true;
return;
}
EventBus.$emit("successful-fs-search", sound.results);
this.freesoundResults = sound.results;
// EventBus.$emit("successful-fs-search", sound.results);
this.showFreesoundResults = true;
},
handleSearchFailure (error) {
Expand Down
201 changes: 201 additions & 0 deletions examples/demos/onsets/src/components/FreesoundResult.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
<template>
<div id="player">
<b-button variant="light" class="not-stretchy" size="sm" id="playbutton" @click="handlePlay">
<b-icon v-show="!playing" icon="play"></b-icon>
<b-icon v-show="playing" icon="pause"></b-icon>
</b-button>
<div id="middle-section">
<div id="titleLink">
<b-link :href="soundResource.url" target="_blank">
{{soundResource.name}}
<sup><b-icon icon="box-arrow-up-right"></b-icon></sup>
</b-link>
</div>
<div id="playbar-container">
<b-form-input type="range" id="playbar" :max="seekMax"
v-model="playbackPosition" size="sm" step="any" @change="handleSeek"></b-form-input>
</div>
</div>
<span class="not-stretchy" id="select-container">
<b-form-checkbox v-model="selected" size="sm"></b-form-checkbox>
</span>
</div>
</template>

<script>
export default {
emits: ['selected'],
props: {
soundResource: Object,
checked: Number
},
data () {
return {
playing: false,
selected: false,
audio: null,
seekMax: 100,
playbackPosition: 0
}
},
watch: {
selected (isSelected) {
if (isSelected) this.$emit('selected');
},
soundResource () {
if (this.audio) {
this.stopAudio();
this.audio = null;
this.playbackPosition = 0;
}
this.setupAudioElement();
},
checked (id) {
if (id != this.soundResource.id) {
this.selected = false;
}
}
},
created () {
this.setupAudioElement();
},
methods: {
handlePlay () {
const whilePlaying = () => {
this.playbackPosition = this.audio.currentTime;
this.rAF = requestAnimationFrame(whilePlaying)
};
if (this.playing) {
this.stopAudio();
return;
}
this.audio.play();
requestAnimationFrame(whilePlaying);
this.playing = true;
},
setupAudioElement () {
this.audio = document.createElement('audio');
this.audio.src = this.soundResource.previews["preview-hq-mp3"];
this.audio.addEventListener('ended', () => {
this.playing = false;
})
const setSliderMax = () => {
this.seekMax = this.audio.duration;
}
if (this.audio.readyState > 0) setSliderMax();
else this.audio.addEventListener('loadedmetadata', setSliderMax.bind(this));
},
handleSeek (pos) {
this.audio.currentTime = Number(pos);
},
stopAudio () {
this.audio.pause();
cancelAnimationFrame(this.rAF)
this.playing = false;
}
}
}
</script>

<style lang="scss" scoped>
@import '../assets/styles/globals.scss';
#player {
display: flex;
flex-direction: row;
justify-content: space-evenly;
&:hover {
background-color: rgba($secondary, 0.1);
}
}
#titleLink {
font-size: 0.75rem;
min-width: 0;
}
#titleLink > a {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#middle-section {
flex: 1 0 70%;
display: grid;
grid-template-rows: minmax(0, 1fr) 1fr;
grid-row-gap: 0;
align-items: center;
justify-items: start;
}
.not-stretchy {
flex: 0;
}
#playbutton {
background-color: rgba($light, 0.5);
z-index: 10;
border-color: transparent;
&:hover {
border-color: $light;
}
}
#playbar-container {
width: 95%;
}
input[type="range"]#playbar {
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
outline: none;
cursor: pointer;
height: .75rem;
&::-webkit-slider-runnable-track {
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
height: 3px;
background-color: $secondary;
}
&::-webkit-slider-thumb {
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
background-color: $dark;
width: 5px;
height: .7rem;
border-radius: 0;
}
&::-moz-range-track {
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
height: 3px;
background-color: $secondary;
}
&::-moz-range-thumb {
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
background-color: $dark;
width: 5px;
height: .7rem;
border-radius: 0;
}
}
#select-container {
margin: auto 0;
}
</style>
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
<template>
<b-form-radio-group v-model="selected" class="row rounded border-0 bg-light py-1 w-100 mx-0">
<div class="col-sm px-0 w-100" v-for="col, colIdx in soundColumns" :key="colIdx">
<b-form-radio-group class="row rounded border-0 bg-light w-100 mx-0">
<div class="col-sm w-100 me-auto" v-for="col, colIdx in soundColumns" :key="colIdx">
<li v-for="sound, sndIdx in col" :key="sndIdx" class="mx-auto">
<iframe frameborder="0" scrolling="no" :src="freesoundEmbedURL(sound.id)" width="375" height="25"></iframe>
<b-form-radio class="select-radio" @change="handleSelect(sound)"></b-form-radio>
<freesound-result :checked="selected" @selected="handleSelect(sound)" :soundResource="sound"></freesound-result>
</li>
</div>
</b-form-radio-group>
</template>

<script>
import EventBus from '../core/event-bus';
import FreesoundResult from './FreesoundResult.vue';
export default {
components: {FreesoundResult},
props: {
sounds: Array
},
data () {
return {
sounds: [],
selected: "",
selected: -1,
cols: 2
}
},
Expand All @@ -34,10 +37,10 @@ export default {
freesoundEmbedURL (soundId) {
return `https://freesound.org/embed/sound/iframe/${soundId}/simple/small/`;
},
populateList (sounds) {
this.sounds = sounds;
},
handleSelect (sound) {
this.selected = sound.id;
},
confirmChoice () {
let selectedAudioURL = sound.previews["preview-hq-mp3"];
EventBus.$emit("sound-selected",
{
Expand All @@ -51,20 +54,22 @@ export default {
);
this.selected = "";
}
},
created () {
EventBus.$on("successful-fs-search", this.populateList);
}
}
</script>

<style scoped>
<style lang="scss" scoped>
@import '../assets/styles/globals.scss';
li {
list-style: none;
}
.select-radio {
display: inline;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
}
</style>

0 comments on commit 22bf4a7

Please sign in to comment.