-
Notifications
You must be signed in to change notification settings - Fork 23
Conversation
Currently everything but the media keys and art are working
Since the last commit artUrl point to a blob object of the Image. However, it still isn't displayed correctly. Currently artUrl looks like this: About the media keys: I'm not exactly sure why those don't work. The current clickButton function does detect the correct buttons ( I guess ), however, click-ing on them doesn't do anything |
If I understood right, blob url are in memory resources than can only be accessed from within the browser. I'd suggest to convert the image blob url to a base64 string (https://stackoverflow.com/questions/18650168/convert-blob-to-base64), that should work if the blob url wasn't revoked.
That looks OK. You can use jsbeautifier to format your js code.
Users can change a service URL by going to Settings > Services > Click on URL.
Weird. Does it work if you run the same code in your browser's javascript console? |
That is not stricly necessary (but I am not a license expert). If you feel like you a want to put a copyright header, you can use the following:
|
Oh, sorry if that wasn't clear, it doesn't work in my browser either. I'm pretty sure that it's the correct element though, it's just that .click() doesn't do anything. Not sure how to debug that, especially with Plex' minified JS code |
You can un-minify javascript from chrome/chromium (Chrome inspector -> Sources tab -> { }) or use http://unminify.com/. |
Ah, thanks. The last commit converts the blob to a base64 encoded image, however, it still doesn't work :/ |
Okay, thanks to a code snippet from Nuvola player everything but media art works now. Thanks for sending me that link! |
I'm still not quite happy with the color scheme, the font is kind of hard to read currently, but with plex' accent color as background color it looks pretty terrible. Maybe you know something better? |
I've tried the theme, I just had to change the foreground color to
Fine 👍
What if you don't use an XMLHttpRequest? If I understood right, a blob url should point to a binary blob in memory and no http request should be necessary. Also, next time, run MellowPlayer with |
So it does create a thumbnail when I don't do a XMLHttpRequest, however the humbnail is just one white pixel. Seems like the base64 string for the thumbnail isn't correct, even though it works fine if I run the code directly in chromium and open the blob url |
Yes the base64 string looks truncated (you may want to use https://codebeautify.org/base64-to-image-converter to check if the string is valid). What if you use the same technique as in the nuvolaplayer plugin? ( https://github.com/tiliado/nuvola-app-plex/blob/master/integrate.js#L146 ) |
As far as I can tell Nuvola's plex plugin doesn't work anymore |
Okay, it seems like MellowPlayer actually can't download the image via the blob URL and the
|
Yes that's normal, you cannot get data from a blob url using an http GET request (see https://stackoverflow.com/questions/30864573/what-is-a-blob-url-and-why-it-is-used). You have to read the blob url from withing the browser using javascritp for that to work. Something like: var reader = new window.FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
base64data = reader.result;
console.log(base64data );
} I'd suggest you try this in your browser and use https://codebeautify.org/base64-to-image-converter to check if the base64 string is valid. If it is valid and MellowPlayer cannot decode/download the image from the same base64 string, then that is a bug. |
Okay, thought MellowPlayer could read it directly from the blob by reading the file directly from its memory,
suggested that to me.
I don't think this will work with just a blob url though, after a bit of googling a4d330c seems like the only approach which works with a blob url. However, that doesn't seem to work with QtWebengine/MellowPlayer ( even though it does with chromium ) |
Awesome, I just applied the patch to 3.1 and it works now! |
Great! Let me know when you think the PR is ready to merge. |
Okay, it should be good to go now! |
Very good work 👍 Just one last thing: do you think you can adapt logo.svg to match the style of the other services logo (gray background / white foreground)? |
Well, thanks for your help :)
Umm..sorry, but I barely know anything about that, would you mind doing that? EDIT: |
Okay, I still get EDIT: Hm, for some reason it works sometimes, but other times I still get this error ( with the same song). |
Okay, so if I run |
plugins/plex/integration.js
Outdated
if (songHash !== previousSongHash) { | ||
artUrl = ""; | ||
convertArtUrlToBase64(); | ||
if (artUrl === "" ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
convertArtUrlToBase64
is asynchronous and set the global artUrl variable later when the response to the XmlHttpRequest has been received and the content loaded by the FileReader. So resetting previousSongHash would cause many redundant request while the response of the first one has not been received.
Can you try the below code and paste the full content of js.log? //-----------------------------------------------------------------------------
//
// This file is part of MellowPlayer.
//
// MellowPlayer is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// MellowPlayer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with MellowPlayer. If not, see <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
// Based in part on utils.js of Nuvolaruntime, which is:
// Copyright 2014-2017 Jiří Janoušek <[email protected]> under the terms of BSD-2:
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
// THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
var previousSongHash = "";
var artUrl = "";
console.warn("initialization")
function convertArtUrlToBase64() {
try {
var artBlobUrl = document.getElementsByClassName('AudioVideoPlayerControls-buttonGroupLeft-3kwFX')[
0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0]
.style["background-image"];
artBlobUrl = artBlobUrl.replace('url("', "").replace('")', "");
console.warn("art blob url: " + artBlobUrl);
// Get the data URL of the blob
var request = new XMLHttpRequest();
request.open('GET', artBlobUrl, true);
request.responseType = 'blob';
request.onload = function() {
console.warn("http response received");
var reader = new FileReader();
reader.onload = function(e) {
console.warn("file reader on load");
artUrl = e.target.result;
console.warn("base 64 url: " + artUrl);
};
reader.readAsDataURL(request.response);
};
request.send();
console.warn("http request sent");
} catch (e) {
console.warn("failed to convertArtUrl: ", e);
}
}
function update() {
var controlClassName = document.getElementsByClassName('AudioVideoPlayerControls-controls-OwK1f')[0];
// if controlClassName is undefined the audioplayer isn't opened yet
if (!controlClassName)
return;
var playbackStatus = mellowplayer.PlaybackStatus.STOPPED;
if (document.querySelector('[aria-label=Pause]') !== null)
playbackStatus = mellowplayer.PlaybackStatus.PLAYING;
else if (document.querySelector('[aria-label=Play]') !== null)
playbackStatus = mellowplayer.PlaybackStatus.PAUSED;
// We'll use this multiple times later on as it packs all the media info
var mediaInfoElement = document.getElementsByClassName('AudioVideoPlayerControls-buttonGroupLeft-3kwFX')[
0].children[0].children[0];
try {
var songTitle = mediaInfoElement.children[1].children[0].title
} catch (e) {
var songTitle = '';
}
try {
var artistInfoElement = mediaInfoElement.children[1].children[1];
var artistName = artistInfoElement.children[0].title;
var albumTitle = artistInfoElement.children[2].title;
} catch (e) {
var artistName = '';
var albumTitle = '';
}
var mediaArtElement = mediaInfoElement.children[
0].children[0].children[0].children[0].children[0].children[0]
var songHash = getHashCode(songTitle + artistName);
if (mediaArtElement && songHash !== previousSongHash) {
console.warn("song changed: " + songTitle + " by " + artistName);
artUrl = "";
convertArtUrlToBase64();
previousSongHash = songHash;
}
var updateInfo = {
"playbackStatus": playbackStatus,
"canSeek": false,
"canGoNext": true,
"canGoPrevious": true,
"canAddToFavorites": false,
"volume": 1,
"duration": mediaTime("duration"),
"position": mediaTime("position"),
"songId": songHash,
"songTitle": songTitle,
"artistName": artistName,
"albumTitle": albumTitle,
"artUrl": artUrl,
"isFavorite": false
};
console.warn("update info: " + JSON.stringify(updateInfo));
return updateInfo;
}
function mediaTime(type) {
var timeElement = document.getElementsByClassName("DurationRemaining-container-1F4w8")[0]
// if timeElement doesn't exist yet the site didn't finish loading yet
if (!timeElement)
return;
else
timeElement = timeElement.innerHTML;
if (type === "position")
// songPosition
var time = timeElement.split("-->")[1].split("<!--")[0];
else
// songDuration
var time = timeElement.split("-->")[5].split("<!--")[0];
return toSeconds(time);
}
function clickButton(buttonName) {
// Taken from: https://github.com/tiliado/nuvolaruntime/blob/master/src/mainjs/utils.js
function triggerMouseEvent(elm, name, x, y) {
var rect = elm.getBoundingClientRect();
var width = rect.width * (x === undefined ? 0.5 : x);
var height = rect.height * (y === undefined ? 0.5 : y);
var opts = {
view: document.defaultView,
bubbles: true,
cancelable: true,
button: 0,
relatedTarget: elm
}
opts.clientX = rect.left + width;
opts.clientY = rect.top + height;
opts.screenX = window.screenX + opts.clientX;
opts.screenY = window.screenY + opts.clientY;
var event = new MouseEvent(name, opts);
elm.dispatchEvent(event);
}
function clickOnElement(elm, x, y) {
triggerMouseEvent(elm, 'mouseover', x, y);
triggerMouseEvent(elm, 'mousedown', x, y);
triggerMouseEvent(elm, 'mouseup', x, y);
triggerMouseEvent(elm, 'click', x, y);
}
clickOnElement(document.querySelector("[aria-label=" + buttonName + "]"))
}
function play() {
clickButton('Play');
}
function pause() {
clickButton('Pause');
}
function goNext() {
clickButton('Next');
}
function goPrevious() {
clickButton('Previous');
}
function setVolume(volume) {
// not supported
}
function addToFavorites() {
// not supported
}
function removeFromFavorites() {
// not supported
}
function seekToPosition(position) {
// not supported
} |
Can you remove js.log and try again (I can only see old log records) |
Hm, I did..anyway, I just re-did it, here: https://paste.pound-python.org/show/2g2rhq19vDWxoYnduoQH/ |
It shows that sometimes the art url to download is not a blob url but a base64 image (1 white pixel). Nothing to do about that. Is that happening only with that song? Does that song sometimes have a valid blob url? |
It always happens with the first song which pops up after the plex plugin loaded. Plex always provides a blob url/image for all songs, in case there's no cover set it plex itself provides a generic cover |
…t artUrl" This reverts commit a3fd9b3.
Ok. I don't see how to fix the first album art url being wrong, we'll have to live with that. |
I guess so, thanks for reviewing! |
The initial bring up for the Plex integration. This is currently a work-in-progess.
Things which have to be fixed:
Also: Since plex servers can be hosted locally it would be nice if one had the ability to set a custom IP for this plugin