ok i got somewhere added buttons but man when i press the buttons the mp3 files are not played and I cannot see any errors anywhere. also the notifications are sent but they are not received by the module I verified that:
here is the updated code of MMM-MP3Player module
MMM-MP3Player.js:
var arrPlayed = [];
Module.register("MMM-MP3Player",{
defaults: {
musicPath: "modules/MMM-MP3Player/music/",
autoPlay: true,
random: false,
loopList: true,
},
getStyles: function() {
return ["style.css"];
},
getDom: function() {
var self = this;
var wrapper = document.createElement("div");
wrapper.id = self.identifier + "_wrapper";
var player = document.createElement("div");
player.className = "player";
self.info = document.createElement("div");
self.info.className = "info";
self.artist = document.createElement("span");
self.artist.className = "artist";
self.artist.innerHTML = "MMM-MP3Player";
self.song = document.createElement("span");
self.song.className = "name";
self.song.innerHTML = self.config.autoPlay ? "AutoPlay Enabled" : "AutoPlay Disabled";
self.song.innerHTML += self.config.random ? "<br />Random Enabled" : "<br />Random Disabled";
var progress = document.createElement("div");
progress.className = "progress-bar";
self.bar = document.createElement("div");
self.bar.className = "bar";
progress.appendChild(self.bar);
self.info.appendChild(self.artist);
self.info.appendChild(self.song);
self.info.appendChild(progress);
self.album_art = document.createElement("div");
self.album_art.className = "album-art";
player.appendChild(self.album_art);
player.appendChild(self.info);
// Controls container
var controls = document.createElement("div");
controls.className = "controls";
// Define buttons and associated notifications
var buttons = {
"Play": 'PLAY_MUSIC',
"Stop": 'STOP_MUSIC',
"Next": 'NEXT_TRACK',
"Previous": 'PREVIOUS_TRACK',
"Random On": 'RANDOM_ON',
"Random Off": 'RANDOM_OFF'
};
Object.keys(buttons).forEach(function(key) {
var button = document.createElement("button");
button.innerHTML = key;
button.addEventListener("click", function() {
console.log("Sending notification:", buttons[key]);
self.sendNotification(buttons[key], 'some_info'); // Sending notification when button is clicked
});
controls.appendChild(button);
});
player.appendChild(controls); // Adding controls to the player
// Initialize the audio element and attach it to 'self' to make it globally accessible within the module
audioElement = document.createElement("audio");
audioElement.id = self.identifier+"_player";
wrapper.appendChild(audioElement);
wrapper.appendChild(player);
setTimeout(function() {
self.sendSocketNotification("INITIATEDEVICES", self.config);
}, 3000);
return wrapper;
},
socketNotificationReceived: function(notification, payload){
var self = this;
switch(notification){
case "Error": // Universal error handler
self.musicFound = false;
console.log("[MMM-MP3Player] Error! ", payload);
break;
case "Music_Files": // this populates the songs list (array)
self.songs = payload;
self.current = 0;
self.musicFound = true;
console.log("[MMM-MP3Player] Music Found");
arrPlayed = Array(self.songs.length).fill(false);
if (self.config.autoPlay){
if (self.config.random){
ind = Math.floor(Math.random() * self.songs.length); //(self.current + 1) % self.songs.length;
arrPlayed[ind] = true;
self.current = ind;
}
self.sendSocketNotification("LOADFILE", self.songs[self.current]);
}
break;
case "Music_File": // this is called everytime a song is sent from the server
//console.log(payload[3]);
if (payload[3] == 'music.png') {
self.album_art.className = "album-art";
self.album_art.classList.add('active');
}
else {
self.album_art.classList.toggle('active');
self.album_art.className = "album-art-found";
var chngstyle = document.querySelector('.album-art-found').style;
chngstyle.setProperty("--backgroundImage", "url('" + payload[3] + "')");
//var mystr = window.getComputedStyle(document.querySelector('.album-art-found'), '::before').getPropertyValue('background-image');
//console.log(mystr);
}
// create url of the raw data received and play it
audioElement=document.getElementById(self.identifier+"_player");
var binaryData = [];
binaryData.push(payload[0]);
if ((payload[2] = 'mp3') || (payload[2] = 'flac')){
var url = window.URL.createObjectURL(new Blob(binaryData, {type: "audio/mpeg"}));
}
/*else if (payload[2] = 'ogg'){
var url = window.URL.createObjectURL(new Blob(binaryData, {type: "audio/ogg"}));
}*/
else if (payload[2] = 'wav'){
var url = window.URL.createObjectURL(new Blob(binaryData, {type: "audio/wav"}));
}
audioElement.load();
audioElement.setAttribute('src', url);
audioElement.volume = 1;
audioElement.play();
self.artist.innerHTML = payload[1][0];
self.song.innerHTML = payload[1][1];
//self.album_art.classList.add('active');
// progress bar (thanks to Michael Foley @ https://codepen.io/mdf/pen/ZWbvBv)
var timer;
var percent = 0;
audioElement.addEventListener("playing", function(_event) {
advance(_event.target.duration, audioElement);
});
audioElement.addEventListener("pause", function(_event) {
clearTimeout(timer);
});
var advance = function(duration, element) {
increment = 10/duration
percent = Math.min(increment * element.currentTime * 10, 100);
self.bar.style.width = percent+'%'
startTimer(duration, element);
}
var startTimer = function(duration, element){
if(percent < 100) {
timer = setTimeout(function (){advance(duration, element)}, 100);
}
}
// next track & loop
audioElement.onended = function() {
if(!self.musicFound){
self.album_art.classList.toggle('active');
return;
}
if (self.config.random){
if (!arrPlayed.includes(false)){ // if all files are played
if (!self.config.loopList) {
self.artist.innerHTML = "Playlist ended";
self.song.innerHTML = "";
console.log("[MMM-MP3Player] Playlist ended");
return;
}
arrPlayed.fill(false);
}
do {
ind = Math.floor(Math.random() * self.songs.length); //(self.current + 1) % self.songs.length;
} while ( (arrPlayed[ind]) || ((ind == self.current) && (self.songs.length>1)) ); //ind == self.current: not to play one song twice - in the end of list and in the beginning of newly created list)
arrPlayed[ind] = true;
self.current = ind;
}
else {
if(self.current==(self.songs.length-1)){ // if all files are played
if (!self.config.loopList){
self.artist.innerHTML = "Playlist ended";
self.song.innerHTML = "";
console.log("[MMM-MP3Player] Playlist ended");
return;
}
self.current = -1;
}
self.current++;
}
self.sendSocketNotification("LOADFILE", self.songs[self.current]);
};
console.log("[MMM-MP3Player] Music Played");
break;
}
},
notificationReceived: function(notification, payload){
var self = this;
if (self.musicFound){
switch(notification){
case "PLAY_MUSIC":
if (audioElement.paused){
audioElement.play();
}
else {
self.sendSocketNotification("LOADFILE", self.songs[self.current]);
}
break;
case "STOP_MUSIC":
audioElement.pause();
break;
case "NEXT_TRACK":
if(!self.musicFound){
self.album_art.classList.toggle('active');
return;
}
if (self.config.random){
if (!arrPlayed.includes(false)){
arrPlayed.fill(false);
}
do {
ind = Math.floor(Math.random() * self.songs.length); // (self.current + 1) % self.songs.length;
} while (arrPlayed[ind] || ind == self.current); // ind == self.current: not to play one song twice - in the end of list and in the beginning of newly created list)
arrPlayed[ind] = true;
self.current = ind;
}
else {
if(self.current==(self.songs.length-1)){ // this assures the loop
self.current = -1;
}
self.current++;
}
self.sendSocketNotification("LOADFILE", self.songs[self.current]);
break;
case "PREVIOUS_TRACK":
if(self.current==0){ // this assures the loop
self.current = (self.songs.length);
}
self.current--;
self.sendSocketNotification("LOADFILE", self.songs[self.current]);
break;
case "RANDOM_ON":
self.config.random = true;
break;
case "RANDOM_OFF":
self.config.random = false;
break;
}
}
}
});
and the css:
/*
* player css is amdended version of Shayan's player @ https://codepen.io/shayanea/pen/yvvjya
* Version 1.2.0 - 2020.09.14
*/
@import url("https://fonts.googleapis.com/css?family=Fira+Sans");
.player {
font-family: "Fira Sans", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
position: relative;
background-color: #fff;
border-radius: 15px;
width: 300px;
height: 80px;
z-index: 5;
-webkit-box-shadow: 0px 0px 117px -6px rgba(255,255,255,1);
-moz-box-shadow: 0px 0px 117px -6px rgba(255,255,255,1);
box-shadow: 0px 0px 117px -6px rgba(255,255,255,1);
display: flex;
/*justify-content: flex-end; */
}
.player .info {
padding: 15px 0px 0px 90px;
width:65%;
}
.player .info .artist,
.player .info .name {
display: block;
line-height: 1.0em;
}
.player .info .artist {
color: #222;
font-size: 16px;
margin-bottom: 4px;
}
.player .info .name {
color: #808080; /*#999*/
font-size: 16px; /*13px*/
margin-bottom: 8px;
}
.player .info .progress-bar {
background-color: #ddd;
height: 3px;
width: 100%;
position: relative;
}
.controls {
display: flex;
justify-content: space-around; /* Distributes space between buttons */
padding: 10px;
}
.controls button {
padding: 5px 10px;
font-size: 14px;
color: white;
background-color: #666; /* Dark grey button background */
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
.controls button:hover {
background-color: #777; /* Lighten button on hover */
}
.controls button:active {
background-color: #555; /* Darken button on active/click */
}
.player .info .progress-bar .bar {
position: absolute;
left: 0;
top: 0;
bottom: 0;
background-color: #666;
transition: all 0.2s ease;
}
.player .album-art-found {
position: absolute;
left: -10px;
height: 80px;
width: 80px;
/* background-color:white; */
box-shadow: 0px 0px 20px 5px rgba(0, 0, 0, 0.2);
transform: scale(1.2);
transition: all 0.5s ease;
}
.player .album-art-found::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-position: center;
background-repeat: no-repeat;
background-size: 80px;
background-image: var(--backgroundImage);
}
.player .album-art {
position: absolute;
left: -10px;
height: 80px;
width: 80px;
border-radius: 50%;
background-color:white;
box-shadow: 0px 0px 20px 5px rgba(0, 0, 0, 0.2);
transform: scale(1.2);
transition: all 0.5s ease;
}
.player .album-art::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 50%;
background-position: center;
background-repeat: no-repeat;
background-size: 50px;
background-image: url("music.png");
}
.player .album-art.active {
box-shadow: 0px 0px 20px 5px rgba(0, 0, 0, 0.4);
transform: scale(1.2);
transition: all 1s ease;
background: linear-gradient(270deg, #2f987d, #4190bd, #d29b2d, #4bd22d, #d2692d, #9e2dd2, #d22daf, #3f2dd2);
background-size: 1600% 1600%;
-webkit-animation: ColorChanger 20s ease infinite;
-moz-animation: ColorChanger 20s ease infinite;
animation: ColorChanger 20s ease infinite;
}
.player .album-art.active::before {
animation: rotation 3s infinite linear;
-webkit-animation: rotation 3s infinite linear;
animation-fill-mode: forwards;
}
@-webkit-keyframes ColorChanger {
0%{background-position:0% 50%}
50%{background-position:100% 50%}
100%{background-position:0% 50%}
}
@-moz-keyframes ColorChanger {
0%{background-position:0% 50%}
50%{background-position:100% 50%}
100%{background-position:0% 50%}
}
@keyframes ColorChanger {
0%{background-position:0% 50%}
50%{background-position:100% 50%}
100%{background-position:0% 50%}
}
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
and the node_helper:
/* Magic Mirror Node Helper: MMM-MP3Player
* By asimhsidd
*
* Remade by Pavel Smelov.
* Version 1.2.0 - 2020.09.14
* GPLv3 License
*/
const NodeHelper = require("node_helper");
const ID3 = require('node-id3');
const path = require('path')
const fs = require('fs');
var music_files_list = [];
module.exports = NodeHelper.create({
socketNotificationReceived: function(notification, payload) {
var self = this;
switch(notification) {
case "INITIATEDEVICES":
music_files_list = [];
var self = this;
self.searchMP3(payload.musicPath);
if(music_files_list.length){
console.log("[MMM-MP3Player] Found ", music_files_list.length, "track(s)");
self.sendSocketNotification("Music_Files",music_files_list);
}
else {
console.log("[MMM-MP3Player] Music may not be found");
}
break;
case "LOADFILE":
//console.log('[MMM-MP3Player] trying to play next track');
if (fs.existsSync(payload)){
fs.readFile(payload, function(err, data) {
extension = path.basename(payload).split('.').pop(); //extension = path.extname(payload); //returns ext with dot
var cover = '';
if (extension == "mp3") {
tags = ID3.read(data);
if (typeof tags.image != "undefined") {
/*var base64String = "";
for (var i = 0; i < tags.image.imageBuffer.length; i++) {
base64String += String.fromCharCode(tags.image.imageBuffer[i]);
}
cover = "data:image/" + tags.image.mime + ";base64," + Buffer.from(base64String).toString('base64'); */
cover = "data:image/" + tags.image.mime + ";base64," + tags.image.imageBuffer.toString('base64');
}
if (typeof tags.artist == "undefined" && typeof tags.title == "undefined"){ tags.title = path.basename(payload); }
}
else {
tags = {artist:'', title:path.basename(payload)};
}
if (cover == '') {
if (fs.existsSync(path.join(path.dirname(payload),'cover.jpg'))){
cover = path.join('/', path.dirname(payload), 'cover.jpg');
}
else {
cover = "music.png";
}
}
self.sendSocketNotification("Music_File",[data,[tags.artist,tags.title], extension, cover]);
});
}
else {
self.sendSocketNotification("Error","File can not be opened");
}
break;
}
},
searchMP3(startPath){ // thanks to Lucio M. Tato at https://stackoverflow.com/questions/25460574/find-files-by-extension-html-under-a-folder-in-nodejs
var self = this;
var filter_mp3 = RegExp('.mp3'); // var filter = /.mp3/;
var filter_flac = RegExp('.flac');
//var filter_ogg = RegExp('.ogg');
var filter_wav = RegExp('.wav');
if (!fs.existsSync(startPath)){
console.log("[MMM-MP3Player] no dir ",startPath);
return;
}
var files=fs.readdirSync(startPath);
for(var i=0;i<files.length;i++){
var filename=path.join(startPath,files[i]);
var stat = fs.lstatSync(filename);
if (stat.isDirectory()){
self.searchMP3(filename); //recurse
}else if ( (filter_mp3.test(filename)) || (filter_flac.test(filename)) /*|| (filter_ogg.test(filename))*/ || (filter_wav.test(filename)) ){
music_files_list.push(filename.replace(/\/\/+/g, '/')); // to avoid double slashes (https://stackoverflow.com/questions/23584117/replace-multiple-slashes-in-text-with-single-slash-with-javascript/23584219)
}
}
}
});
can someone please point me to the right direction ? thanks