episodeSelector functionality added - #10

Open
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master
Open

episodeSelector functionality added#10
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master

Conversation

@theovassiliou

Copy link
Copy Markdown

added a new functionality called episode selector.

Motivation

It is not so uncommon that you would like to randomly select a content from your soundtouch location. In our household, the kids have a demand to have on a specific preset a regularly changing audio book available, but without having to take a computer, phone or tablet into their hands. Other application areas could be to rotate through a list of internet radio stations.

Requirement 1

In order to store a content on a given preset we must be able to reference the content. Soundtouch uses a combination of source, sourceAccount and location information to reference this information. We are using a music libary on a NAS. From this content there is a relatively small amount of content that we want to select from. In our case some 200 episodes. Therefore you should be able to create this pool of content with the information required by the SoundTouch system. For this I created the episodeCollector.js script.

Usage

 node episodeCollector.js

Will start a service that listens to update from a specific device as named in collectorSettings.json.
Select the named device in your SoundTouch-app and select a new content. This content will be added todata-store/libraryContent.json. The file will be created if not existent. Select all content in the SoundTouch-App one by one that you would like to add to the libaryContent. If selecting the same content multple times, only one reference will be created in libraryContent.

Requirement 2

We need a functionality where we can trigger an action that

  • randomly selects one content from libraryContent and
  • stores it at a given preset, if given or the default one, if none is provided

Because of the limitations of the SoundTouch-API it is not possible to store a content directly for a preset. Therefore we introduced the following REST-call

/:deviceName/auto/episodeSelector/:presetKey?

In order to program a preset we

  • select a device
  • start playing the desired content
  • pushing and holding the preset key for around a second
  • releasing the key
  • stopping the playback of the content

Just to make it a little bit safe, we reduce the volume on the device and restore the original volume afterwards.

The function returns a JSON object of the following format:

{
"album": "035 Und Der Hoehlenmensch",
"entry": "0$1$18$3340$19925$20556",
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"presetKey": 6
}

or
416 - Range not satisfied error code with

{
"message": "presetKey should be between 1 and 6"
}

Requirement 3

After a while we did not know exactly what content is stored in the libraryContent. Therefore we introduced a REST-call

 /auto/getAllEpisodes

which returns a list of all episodes as a json object of the format:

{
"0$1$18$3340$19925$21162": {
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"name": "001 - Und der Super Papagei"
},

Final remarks

As a result we have been able to create a small framework to have some content available for selection as preset. By exposing this functionality via a REST-API we are able to regularly change the content of presets for example via a cron-job or similar.

As I believe this could be usefull for other too, I propose this pull request. It should be automatically mergeable

Tested with

I tested this with Soundtouch system consisting of 6 Boses, stored media and internet radio presets.

NOTE

In order to programm a preset we have a push and HOLD the key for a while. A small extension was required in api.js

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@theovassiliou
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

episodeSelector functionality added - #10

Open
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master
Open

episodeSelector functionality added#10
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master

Conversation

@theovassiliou

Copy link
Copy Markdown

added a new functionality called episode selector.

Motivation

It is not so uncommon that you would like to randomly select a content from your soundtouch location. In our household, the kids have a demand to have on a specific preset a regularly changing audio book available, but without having to take a computer, phone or tablet into their hands. Other application areas could be to rotate through a list of internet radio stations.

Requirement 1

In order to store a content on a given preset we must be able to reference the content. Soundtouch uses a combination of source, sourceAccount and location information to reference this information. We are using a music libary on a NAS. From this content there is a relatively small amount of content that we want to select from. In our case some 200 episodes. Therefore you should be able to create this pool of content with the information required by the SoundTouch system. For this I created the episodeCollector.js script.

Usage

 node episodeCollector.js

Will start a service that listens to update from a specific device as named in collectorSettings.json.
Select the named device in your SoundTouch-app and select a new content. This content will be added todata-store/libraryContent.json. The file will be created if not existent. Select all content in the SoundTouch-App one by one that you would like to add to the libaryContent. If selecting the same content multple times, only one reference will be created in libraryContent.

Requirement 2

We need a functionality where we can trigger an action that

  • randomly selects one content from libraryContent and
  • stores it at a given preset, if given or the default one, if none is provided

Because of the limitations of the SoundTouch-API it is not possible to store a content directly for a preset. Therefore we introduced the following REST-call

/:deviceName/auto/episodeSelector/:presetKey?

In order to program a preset we

  • select a device
  • start playing the desired content
  • pushing and holding the preset key for around a second
  • releasing the key
  • stopping the playback of the content

Just to make it a little bit safe, we reduce the volume on the device and restore the original volume afterwards.

The function returns a JSON object of the following format:

{
"album": "035 Und Der Hoehlenmensch",
"entry": "0$1$18$3340$19925$20556",
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"presetKey": 6
}

or
416 - Range not satisfied error code with

{
"message": "presetKey should be between 1 and 6"
}

Requirement 3

After a while we did not know exactly what content is stored in the libraryContent. Therefore we introduced a REST-call

 /auto/getAllEpisodes

which returns a list of all episodes as a json object of the format:

{
"0$1$18$3340$19925$21162": {
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"name": "001 - Und der Super Papagei"
},

Final remarks

As a result we have been able to create a small framework to have some content available for selection as preset. By exposing this functionality via a REST-API we are able to regularly change the content of presets for example via a cron-job or similar.

As I believe this could be usefull for other too, I propose this pull request. It should be automatically mergeable

Tested with

I tested this with Soundtouch system consisting of 6 Boses, stored media and internet radio presets.

NOTE

In order to programm a preset we have a push and HOLD the key for a while. A small extension was required in api.js

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@theovassiliou
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

episodeSelector functionality added - #10

Open
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master
Open

episodeSelector functionality added#10
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master

Conversation

@theovassiliou

Copy link
Copy Markdown

added a new functionality called episode selector.

Motivation

It is not so uncommon that you would like to randomly select a content from your soundtouch location. In our household, the kids have a demand to have on a specific preset a regularly changing audio book available, but without having to take a computer, phone or tablet into their hands. Other application areas could be to rotate through a list of internet radio stations.

Requirement 1

In order to store a content on a given preset we must be able to reference the content. Soundtouch uses a combination of source, sourceAccount and location information to reference this information. We are using a music libary on a NAS. From this content there is a relatively small amount of content that we want to select from. In our case some 200 episodes. Therefore you should be able to create this pool of content with the information required by the SoundTouch system. For this I created the episodeCollector.js script.

Usage

 node episodeCollector.js

Will start a service that listens to update from a specific device as named in collectorSettings.json.
Select the named device in your SoundTouch-app and select a new content. This content will be added todata-store/libraryContent.json. The file will be created if not existent. Select all content in the SoundTouch-App one by one that you would like to add to the libaryContent. If selecting the same content multple times, only one reference will be created in libraryContent.

Requirement 2

We need a functionality where we can trigger an action that

  • randomly selects one content from libraryContent and
  • stores it at a given preset, if given or the default one, if none is provided

Because of the limitations of the SoundTouch-API it is not possible to store a content directly for a preset. Therefore we introduced the following REST-call

/:deviceName/auto/episodeSelector/:presetKey?

In order to program a preset we

  • select a device
  • start playing the desired content
  • pushing and holding the preset key for around a second
  • releasing the key
  • stopping the playback of the content

Just to make it a little bit safe, we reduce the volume on the device and restore the original volume afterwards.

The function returns a JSON object of the following format:

{
"album": "035 Und Der Hoehlenmensch",
"entry": "0$1$18$3340$19925$20556",
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"presetKey": 6
}

or
416 - Range not satisfied error code with

{
"message": "presetKey should be between 1 and 6"
}

Requirement 3

After a while we did not know exactly what content is stored in the libraryContent. Therefore we introduced a REST-call

 /auto/getAllEpisodes

which returns a list of all episodes as a json object of the format:

{
"0$1$18$3340$19925$21162": {
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"name": "001 - Und der Super Papagei"
},

Final remarks

As a result we have been able to create a small framework to have some content available for selection as preset. By exposing this functionality via a REST-API we are able to regularly change the content of presets for example via a cron-job or similar.

As I believe this could be usefull for other too, I propose this pull request. It should be automatically mergeable

Tested with

I tested this with Soundtouch system consisting of 6 Boses, stored media and internet radio presets.

NOTE

In order to programm a preset we have a push and HOLD the key for a while. A small extension was required in api.js

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@theovassiliou
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

episodeSelector functionality added - #10

Open
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master
Open

episodeSelector functionality added#10
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master

Conversation

@theovassiliou

Copy link
Copy Markdown

added a new functionality called episode selector.

Motivation

It is not so uncommon that you would like to randomly select a content from your soundtouch location. In our household, the kids have a demand to have on a specific preset a regularly changing audio book available, but without having to take a computer, phone or tablet into their hands. Other application areas could be to rotate through a list of internet radio stations.

Requirement 1

In order to store a content on a given preset we must be able to reference the content. Soundtouch uses a combination of source, sourceAccount and location information to reference this information. We are using a music libary on a NAS. From this content there is a relatively small amount of content that we want to select from. In our case some 200 episodes. Therefore you should be able to create this pool of content with the information required by the SoundTouch system. For this I created the episodeCollector.js script.

Usage

 node episodeCollector.js

Will start a service that listens to update from a specific device as named in collectorSettings.json.
Select the named device in your SoundTouch-app and select a new content. This content will be added todata-store/libraryContent.json. The file will be created if not existent. Select all content in the SoundTouch-App one by one that you would like to add to the libaryContent. If selecting the same content multple times, only one reference will be created in libraryContent.

Requirement 2

We need a functionality where we can trigger an action that

  • randomly selects one content from libraryContent and
  • stores it at a given preset, if given or the default one, if none is provided

Because of the limitations of the SoundTouch-API it is not possible to store a content directly for a preset. Therefore we introduced the following REST-call

/:deviceName/auto/episodeSelector/:presetKey?

In order to program a preset we

  • select a device
  • start playing the desired content
  • pushing and holding the preset key for around a second
  • releasing the key
  • stopping the playback of the content

Just to make it a little bit safe, we reduce the volume on the device and restore the original volume afterwards.

The function returns a JSON object of the following format:

{
"album": "035 Und Der Hoehlenmensch",
"entry": "0$1$18$3340$19925$20556",
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"presetKey": 6
}

or
416 - Range not satisfied error code with

{
"message": "presetKey should be between 1 and 6"
}

Requirement 3

After a while we did not know exactly what content is stored in the libraryContent. Therefore we introduced a REST-call

 /auto/getAllEpisodes

which returns a list of all episodes as a json object of the format:

{
"0$1$18$3340$19925$21162": {
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"name": "001 - Und der Super Papagei"
},

Final remarks

As a result we have been able to create a small framework to have some content available for selection as preset. By exposing this functionality via a REST-API we are able to regularly change the content of presets for example via a cron-job or similar.

As I believe this could be usefull for other too, I propose this pull request. It should be automatically mergeable

Tested with

I tested this with Soundtouch system consisting of 6 Boses, stored media and internet radio presets.

NOTE

In order to programm a preset we have a push and HOLD the key for a while. A small extension was required in api.js

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@theovassiliou
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

episodeSelector functionality added - #10

Open
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master
Open

episodeSelector functionality added#10
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master

Conversation

@theovassiliou

Copy link
Copy Markdown

added a new functionality called episode selector.

Motivation

It is not so uncommon that you would like to randomly select a content from your soundtouch location. In our household, the kids have a demand to have on a specific preset a regularly changing audio book available, but without having to take a computer, phone or tablet into their hands. Other application areas could be to rotate through a list of internet radio stations.

Requirement 1

In order to store a content on a given preset we must be able to reference the content. Soundtouch uses a combination of source, sourceAccount and location information to reference this information. We are using a music libary on a NAS. From this content there is a relatively small amount of content that we want to select from. In our case some 200 episodes. Therefore you should be able to create this pool of content with the information required by the SoundTouch system. For this I created the episodeCollector.js script.

Usage

 node episodeCollector.js

Will start a service that listens to update from a specific device as named in collectorSettings.json.
Select the named device in your SoundTouch-app and select a new content. This content will be added todata-store/libraryContent.json. The file will be created if not existent. Select all content in the SoundTouch-App one by one that you would like to add to the libaryContent. If selecting the same content multple times, only one reference will be created in libraryContent.

Requirement 2

We need a functionality where we can trigger an action that

  • randomly selects one content from libraryContent and
  • stores it at a given preset, if given or the default one, if none is provided

Because of the limitations of the SoundTouch-API it is not possible to store a content directly for a preset. Therefore we introduced the following REST-call

/:deviceName/auto/episodeSelector/:presetKey?

In order to program a preset we

  • select a device
  • start playing the desired content
  • pushing and holding the preset key for around a second
  • releasing the key
  • stopping the playback of the content

Just to make it a little bit safe, we reduce the volume on the device and restore the original volume afterwards.

The function returns a JSON object of the following format:

{
"album": "035 Und Der Hoehlenmensch",
"entry": "0$1$18$3340$19925$20556",
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"presetKey": 6
}

or
416 - Range not satisfied error code with

{
"message": "presetKey should be between 1 and 6"
}

Requirement 3

After a while we did not know exactly what content is stored in the libraryContent. Therefore we introduced a REST-call

 /auto/getAllEpisodes

which returns a list of all episodes as a json object of the format:

{
"0$1$18$3340$19925$21162": {
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"name": "001 - Und der Super Papagei"
},

Final remarks

As a result we have been able to create a small framework to have some content available for selection as preset. By exposing this functionality via a REST-API we are able to regularly change the content of presets for example via a cron-job or similar.

As I believe this could be usefull for other too, I propose this pull request. It should be automatically mergeable

Tested with

I tested this with Soundtouch system consisting of 6 Boses, stored media and internet radio presets.

NOTE

In order to programm a preset we have a push and HOLD the key for a while. A small extension was required in api.js

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@theovassiliou
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

episodeSelector functionality added - #10

Open
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master
Open

episodeSelector functionality added#10
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master

Conversation

@theovassiliou

Copy link
Copy Markdown

added a new functionality called episode selector.

Motivation

It is not so uncommon that you would like to randomly select a content from your soundtouch location. In our household, the kids have a demand to have on a specific preset a regularly changing audio book available, but without having to take a computer, phone or tablet into their hands. Other application areas could be to rotate through a list of internet radio stations.

Requirement 1

In order to store a content on a given preset we must be able to reference the content. Soundtouch uses a combination of source, sourceAccount and location information to reference this information. We are using a music libary on a NAS. From this content there is a relatively small amount of content that we want to select from. In our case some 200 episodes. Therefore you should be able to create this pool of content with the information required by the SoundTouch system. For this I created the episodeCollector.js script.

Usage

 node episodeCollector.js

Will start a service that listens to update from a specific device as named in collectorSettings.json.
Select the named device in your SoundTouch-app and select a new content. This content will be added todata-store/libraryContent.json. The file will be created if not existent. Select all content in the SoundTouch-App one by one that you would like to add to the libaryContent. If selecting the same content multple times, only one reference will be created in libraryContent.

Requirement 2

We need a functionality where we can trigger an action that

  • randomly selects one content from libraryContent and
  • stores it at a given preset, if given or the default one, if none is provided

Because of the limitations of the SoundTouch-API it is not possible to store a content directly for a preset. Therefore we introduced the following REST-call

/:deviceName/auto/episodeSelector/:presetKey?

In order to program a preset we

  • select a device
  • start playing the desired content
  • pushing and holding the preset key for around a second
  • releasing the key
  • stopping the playback of the content

Just to make it a little bit safe, we reduce the volume on the device and restore the original volume afterwards.

The function returns a JSON object of the following format:

{
"album": "035 Und Der Hoehlenmensch",
"entry": "0$1$18$3340$19925$20556",
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"presetKey": 6
}

or
416 - Range not satisfied error code with

{
"message": "presetKey should be between 1 and 6"
}

Requirement 3

After a while we did not know exactly what content is stored in the libraryContent. Therefore we introduced a REST-call

 /auto/getAllEpisodes

which returns a list of all episodes as a json object of the format:

{
"0$1$18$3340$19925$21162": {
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"name": "001 - Und der Super Papagei"
},

Final remarks

As a result we have been able to create a small framework to have some content available for selection as preset. By exposing this functionality via a REST-API we are able to regularly change the content of presets for example via a cron-job or similar.

As I believe this could be usefull for other too, I propose this pull request. It should be automatically mergeable

Tested with

I tested this with Soundtouch system consisting of 6 Boses, stored media and internet radio presets.

NOTE

In order to programm a preset we have a push and HOLD the key for a while. A small extension was required in api.js

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@theovassiliou
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

episodeSelector functionality added - #10

Open
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master
Open

episodeSelector functionality added#10
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master

Conversation

@theovassiliou

Copy link
Copy Markdown

added a new functionality called episode selector.

Motivation

It is not so uncommon that you would like to randomly select a content from your soundtouch location. In our household, the kids have a demand to have on a specific preset a regularly changing audio book available, but without having to take a computer, phone or tablet into their hands. Other application areas could be to rotate through a list of internet radio stations.

Requirement 1

In order to store a content on a given preset we must be able to reference the content. Soundtouch uses a combination of source, sourceAccount and location information to reference this information. We are using a music libary on a NAS. From this content there is a relatively small amount of content that we want to select from. In our case some 200 episodes. Therefore you should be able to create this pool of content with the information required by the SoundTouch system. For this I created the episodeCollector.js script.

Usage

 node episodeCollector.js

Will start a service that listens to update from a specific device as named in collectorSettings.json.
Select the named device in your SoundTouch-app and select a new content. This content will be added todata-store/libraryContent.json. The file will be created if not existent. Select all content in the SoundTouch-App one by one that you would like to add to the libaryContent. If selecting the same content multple times, only one reference will be created in libraryContent.

Requirement 2

We need a functionality where we can trigger an action that

  • randomly selects one content from libraryContent and
  • stores it at a given preset, if given or the default one, if none is provided

Because of the limitations of the SoundTouch-API it is not possible to store a content directly for a preset. Therefore we introduced the following REST-call

/:deviceName/auto/episodeSelector/:presetKey?

In order to program a preset we

  • select a device
  • start playing the desired content
  • pushing and holding the preset key for around a second
  • releasing the key
  • stopping the playback of the content

Just to make it a little bit safe, we reduce the volume on the device and restore the original volume afterwards.

The function returns a JSON object of the following format:

{
"album": "035 Und Der Hoehlenmensch",
"entry": "0$1$18$3340$19925$20556",
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"presetKey": 6
}

or
416 - Range not satisfied error code with

{
"message": "presetKey should be between 1 and 6"
}

Requirement 3

After a while we did not know exactly what content is stored in the libraryContent. Therefore we introduced a REST-call

 /auto/getAllEpisodes

which returns a list of all episodes as a json object of the format:

{
"0$1$18$3340$19925$21162": {
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"name": "001 - Und der Super Papagei"
},

Final remarks

As a result we have been able to create a small framework to have some content available for selection as preset. By exposing this functionality via a REST-API we are able to regularly change the content of presets for example via a cron-job or similar.

As I believe this could be usefull for other too, I propose this pull request. It should be automatically mergeable

Tested with

I tested this with Soundtouch system consisting of 6 Boses, stored media and internet radio presets.

NOTE

In order to programm a preset we have a push and HOLD the key for a while. A small extension was required in api.js

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@theovassiliou
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

episodeSelector functionality added - #10

Open
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master
Open

episodeSelector functionality added#10
theovassiliou wants to merge 17 commits into
Adeptive:masterfrom
theovassiliou:master

Conversation

@theovassiliou

Copy link
Copy Markdown

added a new functionality called episode selector.

Motivation

It is not so uncommon that you would like to randomly select a content from your soundtouch location. In our household, the kids have a demand to have on a specific preset a regularly changing audio book available, but without having to take a computer, phone or tablet into their hands. Other application areas could be to rotate through a list of internet radio stations.

Requirement 1

In order to store a content on a given preset we must be able to reference the content. Soundtouch uses a combination of source, sourceAccount and location information to reference this information. We are using a music libary on a NAS. From this content there is a relatively small amount of content that we want to select from. In our case some 200 episodes. Therefore you should be able to create this pool of content with the information required by the SoundTouch system. For this I created the episodeCollector.js script.

Usage

 node episodeCollector.js

Will start a service that listens to update from a specific device as named in collectorSettings.json.
Select the named device in your SoundTouch-app and select a new content. This content will be added todata-store/libraryContent.json. The file will be created if not existent. Select all content in the SoundTouch-App one by one that you would like to add to the libaryContent. If selecting the same content multple times, only one reference will be created in libraryContent.

Requirement 2

We need a functionality where we can trigger an action that

  • randomly selects one content from libraryContent and
  • stores it at a given preset, if given or the default one, if none is provided

Because of the limitations of the SoundTouch-API it is not possible to store a content directly for a preset. Therefore we introduced the following REST-call

/:deviceName/auto/episodeSelector/:presetKey?

In order to program a preset we

  • select a device
  • start playing the desired content
  • pushing and holding the preset key for around a second
  • releasing the key
  • stopping the playback of the content

Just to make it a little bit safe, we reduce the volume on the device and restore the original volume afterwards.

The function returns a JSON object of the following format:

{
"album": "035 Und Der Hoehlenmensch",
"entry": "0$1$18$3340$19925$20556",
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"presetKey": 6
}

or
416 - Range not satisfied error code with

{
"message": "presetKey should be between 1 and 6"
}

Requirement 3

After a while we did not know exactly what content is stored in the libraryContent. Therefore we introduced a REST-call

 /auto/getAllEpisodes

which returns a list of all episodes as a json object of the format:

{
"0$1$18$3340$19925$21162": {
"source": "STORED_MUSIC",
"sourceAccount": "55076f6e-6b79-1d65-a4eb-00089bea8bd7/0",
"name": "001 - Und der Super Papagei"
},

Final remarks

As a result we have been able to create a small framework to have some content available for selection as preset. By exposing this functionality via a REST-API we are able to regularly change the content of presets for example via a cron-job or similar.

As I believe this could be usefull for other too, I propose this pull request. It should be automatically mergeable

Tested with

I tested this with Soundtouch system consisting of 6 Boses, stored media and internet radio presets.

NOTE

In order to programm a preset we have a push and HOLD the key for a while. A small extension was required in api.js

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@theovassiliou