Skip to content

Commit

Permalink
feat: reverb effect settings (#177)
Browse files Browse the repository at this point in the history
  • Loading branch information
cdrani authored Nov 16, 2023
1 parent 6c5cda3 commit 70a2678
Show file tree
Hide file tree
Showing 44 changed files with 854 additions and 441 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "chorus",
"private": true,
"type": "module",
"version": "1.16.2",
"version": "1.17.0",
"scripts": {
"build": "rollup -c",
"watch": "rollup -c -w"
Expand Down
7 changes: 4 additions & 3 deletions src/actions/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import App from '../models/app.js'

async function load() {
await store.populate()
const app = new App(spotifyVideo.element)

const app = new App({ video: spotifyVideo.element, reverb: spotifyVideo.reverb })
const enabled = JSON.parse(sessionStorage.getItem('enabled') ?? 'true')

enabled ? await app.connect() : app.disconnect()
enabled ? app.connect() : app.disconnect()
spotifyVideo.element.active = enabled

document.addEventListener('app.enabled', async e => {
Expand All @@ -19,7 +20,7 @@ async function load() {

sessionStorage.setItem('enabled', enabled.newValue)
spotifyVideo.element.active = enabled.newValue
enabled.newValue ? await app.connect() : app.disconnect()
enabled.newValue ? app.connect() : app.disconnect()
})

document.addEventListener('app.device_id', async e => {
Expand Down
43 changes: 11 additions & 32 deletions src/actions/overload.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,32 @@
import Reverb from '../models/reverb/reverb.js'
import VideoElement from '../models/video/video.js'

class SpotifyVideo {
#video
#tries = 0
#originalCreateElement = document.createElement

constructor() {
this.#overloadCreateElement()
this._video
this._reverb
this._originalCreateElement = document.createElement
this.#init()
}

#overloadCreateElement() {
#init() {
const self = this

document.createElement = function (tagName) {
const element = self.#originalCreateElement.apply(this, arguments)
const element = self._originalCreateElement.apply(this, arguments)

if (tagName === 'video') {
self.#video = new VideoElement(element)

document.createElement = self.#originalCreateElement
self._reverb = new Reverb(element)
self._video = new VideoElement({ video: element, reverb: self._reverb })
document.createElement = self._originalCreateElement
}
return element
}
}

#init = () => {
try {
this.#tries++
this.#checkForMainEl()
} catch {
if (this.#tries <= 20) {
setTimeout(this.#init, 500)
return
}
}
}

#checkForMainEl() {
const mainEl = document.getElementById('main')
get element() { return this._video }

if (mainEl === null) {
throw new Error('Main container element not found')
}
}

get element() {
return this.#video
}
get reverb() { return this._reverb }
}

export const spotifyVideo = new SpotifyVideo()
30 changes: 16 additions & 14 deletions src/background.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { setState, getState } from './utils/state.js'
import { getActiveTab, sendMessage } from './utils/messaging.js'

import { playSharedTrack } from './services/player.js'
import { createArtistDiscoPlaylist } from './services/artist-disco.js'
import { playSharedTrack, seekTrackToPosition } from './services/player.js'

let ENABLED = true
let popupPort = null
Expand Down Expand Up @@ -79,20 +79,22 @@ chrome.webRequest.onBeforeSendHeaders.addListener(details => {
['requestHeaders']
)

chrome.runtime.onMessage.addListener(({ key, data }, _, sendResponse) => {
switch (key) {
case 'artist.disco':
createArtistDiscoPlaylist(data)
.then(result => sendResponse({ state: 'completed', data: result }))
.catch(error => sendResponse({ state: 'error', error: error.message }))
return true
case 'play.shared':
playSharedTrack(data)
.then(result => sendResponse({ state: 'completed', data: result }))
.catch(error => sendResponse({ state: 'error', error: error.message }))

return true
function promiseHandler(promise, sendResponse) {
promise.then(result => sendResponse({ state: 'completed', data: result }))
.catch(error => sendResponse({ state: 'error', error: error.message }))
}

chrome.runtime.onMessage.addListener(({ key, values }, _, sendResponse) => {
const messageHandler = {
'play.shared': playSharedTrack,
'play.seek': seekTrackToPosition,
'artist-disco': createArtistDiscoPlaylist,
}
const handlerFn = messageHandler[key]
if (!handlerFn) return

promiseHandler(handlerFn(values), sendResponse)
return true
})

chrome.commands.onCommand.addListener(async command => {
Expand Down
8 changes: 8 additions & 0 deletions src/components/effects/effects-button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createTextButton } from '../text-button.js'

export const createEffectsButtons = () => `
<div style="display:flex;margin-top:12px;justify-content:space-between;height:1.5rem;">
${createTextButton({ text: 'reset', id: 'effects-reset' })}
${createTextButton({ text: 'save', id: 'effects-save' })}
</div>
`
20 changes: 20 additions & 0 deletions src/components/effects/effects-controls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createEffectsButtons } from './effects-button.js'
import { createEffectsSelector } from './effects-selector.js'
import { convolverPresets, drinkPresets } from '../../lib/reverb/presets.js'

export const createEffectsControls = () => `
<div id="chorus-fx-controls" style="display: none">
<div style="display:flex;flex-direction:column;justify-content:space-evenly;height:6rem;">
${createEffectsSelector({ name: 'drink-effect', labelName: 'cup-sized reverb', optionNames: drinkPresets })}
${createEffectsSelector({ name: 'convolver-effect', labelName: 'impulse reverb', optionNames: convolverPresets })}
<hr/>
<div style="font-size:1rem;color:#b3b3b3;">
<p style="display:flex;justify-content:space-between;width:100%;padding-right:.125rem;">
effect <span id="preset-selection" style="color:#fff"></span>
</p>
</div>
</div>
${createEffectsButtons()}
</div>
`
21 changes: 21 additions & 0 deletions src/components/effects/effects-selector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const createOptions = optionNames => (
optionNames.map(name => `<option name="${name}" value="${name}">${name}</option>`).join('')
)

export const createEffectsSelector = ({ labelName, name, optionNames }) => `
<div style="display:flex;justify-content:space-between">
<label style="color:#b3b3b3;font-size:">${labelName}</label>
<form id="select-container" class="selector">
<select
class="select"
id="${name}-presets"
name="${name}-presets"
style="color:#fff;font-size:1rem;text-align:end"
>
<option name="none" value="none">-----</option>
${createOptions(optionNames)}
</select>
</form>
</div>
`
1 change: 1 addition & 0 deletions src/components/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const createHeader = () => `
<div style="display:flex;height:25px;align-items:center;justify-content:space-around;">
${createHeaderButton({ role: 'snip', ariaLabel: 'Snip Controls', additionalStyles: 'background-color:green;' })}
${createHeaderButton({ role: 'speed', ariaLabel: 'Speed Controls', additionalStyles: 'margin-left:.5rem;' })}
${createHeaderButton({ role: 'fx', ariaLabel: 'FX Controls', additionalStyles: 'margin-left:.5rem;' })}
${createHeaderButton({ role: 'seek', ariaLabel: 'Seek Controls', additionalStyles: 'margin:0 .5rem;' })}
</div>
Expand Down
22 changes: 13 additions & 9 deletions src/components/text-button.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
export const createTextButton = ({ id, text, style }) => `
<button
id="chorus-${id}-button"
class="chorus-text-button"
style="padding:0 10px;height:100%;font-size:1rem;${style || ''}"
>
<span>${text}</span>
</button>
`
const classNames = { share: 'share', save: 'success', reset: 'danger', remove: 'danger' }

export const createTextButton = ({ id, text, style }) => {
const btnTypeClass = classNames[id?.split('-')?.at(-1)]
return `
<button
id="chorus-${id}-button"
class="chorus-text-button ${btnTypeClass ?? ''}"
style="padding:0 10px;height:100%;font-size:1rem;${style || ''}"
>
<span>${text}</span>
</button>
`
}
6 changes: 3 additions & 3 deletions src/components/track-info.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const createTrackInfo = () => `
<div style="display:flex;flex-direction:column;margin-top:0.5rem;">
<p id="track-title" style="color:#fff;font-size:14px;"></p>
<p id="track-artists" style="font-size:11px;color:#b3b3b3;"></p>
<div style="display:flex;flex-direction:column;width:100%;justify-content:space-evenly;margin-top:.5rem">
<div class="container" style="width:282px"><div class="track-text" id="track-title"></div></div>
<div class="container" style="width:282px"><div class="track-text" id="track-artists"></div></div>
</div>
`
57 changes: 20 additions & 37 deletions src/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,38 @@ const loadScript = filePath => {
const script = document.createElement('script')
script.src = chrome.runtime.getURL(filePath)
script.type = 'module'
document.body.appendChild(script)
document.head.appendChild(script)
script.onload = () => { script.remove() }
}

loadScript('actions/init.js')
sessionStorage.setItem('soundsDir', chrome.runtime.getURL('/lib/sounds/'))
sessionStorage.setItem('reverbPath', chrome.runtime.getURL('/lib/reverb/reverb.js'))

const sendEventToPage = ({ eventType, detail }) => {
window.postMessage({
type: 'FROM_CONTENT_SCRIPT',
requestType: eventType,
payload: detail
}, window.location.origin)
window.postMessage({ type: 'FROM_CONTENT_SCRIPT', requestType: eventType, payload: detail }, window.location.origin)
}

window.addEventListener('message', async (event) => {
if (event.origin !== window.location.origin) return
if (event.data.type !== 'FROM_PAGE_SCRIPT') return

const { requestType, payload } = event.data
let response

switch (requestType) {
case 'artist.disco':
response = await sendBackgroundMessage({ key: payload.key, data: payload.values })
sendEventToPage({ eventType: 'artist.disco.response', detail: response })
break
case 'play.shared':
response = await sendBackgroundMessage({ key: payload.key, data: payload.values })
sendEventToPage({ eventType: 'play.shared.response', detail: response })
break
case 'storage.set':
const { key, values } = payload
response = await setState({ key, values })
sendEventToPage({ eventType: 'storage.set.response', detail: response })
break

case 'storage.get':
response = await getState(payload?.key)
sendEventToPage({ eventType: 'storage.get.response', detail: response })
break

case 'storage.delete':
await removeState(payload.key)
break

case 'storage.populate':
response = await getState(null)
sendEventToPage({ eventType: 'storage.populate.response', detail: response })
break
}
const messageHandlers = {
'play.seek': sendBackgroundMessage,
'play.shared': sendBackgroundMessage,
'artist.disco': sendBackgroundMessage,
'storage.populate': () => getState(null),
'storage.get': ({ key }) => getState(key),
'storage.delete': ({ key }) => removeState(key),
'storage.set': ({ key, values }) => setState({ key, values }),
};

const handlerFn = messageHandlers[requestType]
if (!handlerFn) return

const response = await handlerFn(payload)
sendEventToPage({ eventType: `${requestType}.response`, detail: response })
})

chrome.runtime.onMessage.addListener(message => {
Expand Down
Loading

0 comments on commit 70a2678

Please sign in to comment.