MagicMirror Forum
    • Recent
    • Tags
    • Unsolved
    • Solved
    • MagicMirror² Repository
    • Documentation
    • 3rd-Party-Modules
    • Donate
    • Discord
    • Register
    • Login
    1. Home
    2. hokie-bird
    3. Posts
    A New Chapter for MagicMirror: The Community Takes the Lead
    Read the statement by Michael Teeuw here.
    H
    Offline
    • Profile
    • Following 0
    • Followers 0
    • Topics 2
    • Posts 7
    • Groups 0

    Posts

    Recent Best Controversial
    • RE: DIY Module Displays Nothing

      It was the fade! when I switch the fade to 0, even the refresh of 1 seconds works and displays perfectly. @sdetweil you are brilliant!

      Thank you!

      posted in Troubleshooting
      H
      hokie-bird
    • RE: DIY Module Displays Nothing

      Thank you again @sdetweil

      I implemented both of your changes (removing sendSocketNotification() in start and 5 second refresh interval) and it seems the refresh interval is what is impacting the display. At 1 second, basically nothing, but at 5 seconds I get a 5 second display, then maybe a 2 second disappearance and then a 5 second display repeating pattern. (Which is somewhat interesting as the browser console is reporting accurate data every 1 second, despite nothing being displayed.) Not sure how to get a constant/non-disappearing display (when music is playing) while still getting an accurate reflection/countdown of the time remain, but I’ll experiment with that.

      Of course, suggestions welcome. And thanks again.

      posted in Troubleshooting
      H
      hokie-bird
    • RE: DIY Module Displays Nothing

      @sdetweil cant thank you enough for taking the time to do that, WOW!

      Here’s what I’ve learned. I subbed your LyrionNowPlaying.js in for mine, and results were exactly the same: “No song currently playing” at startup for a second or two, vanishes and never returns despite music starting/stopping. Then I subbed your node_helper.js for mine (with your module.js file and .png) and BOOM! your data and image appeared! Granted, it would appear for 4 seconds or so, disappear for 1-2, then re-appear but progress! So, safe to assume its somehow something in my node_helper? Here’s the latest, and again wildly grateful for your help.

      node_helper.js

      const NodeHelper = require('node_helper');
      const request = require('request');
      
      module.exports = NodeHelper.create({
      
          start: function() {
              console.log("Starting node_helper for: " + this.name);
              this.nowPlaying = { 
                  artist: "", 
                  song: "",
                  timeRemaining: "",
                  duration: 0, 
                  position: 0,
                  coverArt: "" 
              }; 
              this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', this.nowPlaying); // Send initial empty state
          },
      
          socketNotificationReceived: function(notification, payload) {
              if (notification === 'GET_LYRION_NOW_PLAYING') {
                  this.getLyrionNowPlaying(payload);
              }
          },
      
          getLyrionNowPlaying: function(payload) {
              const { lyrionServer, playerName } = payload;
              const options = {
                  url: `${lyrionServer}/jsonrpc.js`,
                  method: 'POST',
                  headers: {
                      'Content-Type': 'application/json'
                  },
                  body: JSON.stringify({
                      "id": 1,
                      "method": "slim.request",
                      "params": [playerName, ["status", "-", 1, "tags:artist"]] 
                  })
              };
      
              request(options, (error, response, body) => {
                  if (error) {
                      console.error(`MMM-LyrionNowPlaying: Error connecting to Lyrion server: ${error}`);
                      this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', { error: `Error connecting to Lyrion server: ${error}` });
                      return;
                  }
      
                  if (response.statusCode !== 200) {
                      console.error(`MMM-LyrionNowPlaying: Received unexpected status code from Lyrion server: ${response.statusCode}`);
                      this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', { error: `Received unexpected status code from Lyrion server: ${response.statusCode}` });
                      return;
                  }
      
                  try {
                      const data = JSON.parse(body);
                      console.log("Raw Data:", data); 
      
                      if (!data.result) {
                          console.error(`MMM-LyrionNowPlaying: Invalid response from Lyrion server: Missing 'result' in response`);
                          this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', { error: `Invalid response from Lyrion server: Missing 'result' in response` });
                          return;
                      }
      
                      if (!data.result.mode || data.result.mode !== 'play') { 
                          this.nowPlaying = { 
                              artist: "", 
                              song: "",
                              timeRemaining: "",
                              duration: 0, 
                              position: 0,
                              coverArt: "" 
                          }; 
                          this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', this.nowPlaying); // Send "no song" notification immediately
                          return; 
                      }
      
                      // Handle cases where playlist_loop might be missing or empty
                      let artist = "Unknown Artist";
                      let song = "Unknown Song";
      
                      if (data.result.playlist_loop && data.result.playlist_loop[0]) {
                          artist = data.result.playlist_loop[0].artist || "Unknown Artist";
                          song = data.result.playlist_loop[0].title || "Unknown Song"; 
                      }
      
                      this.nowPlaying = {
                          artist: artist,
                          song: song,
                          duration: data.result.duration || 0, 
                          position: data.result.time || 0,
                          coverArt: `${lyrionServer}/music/current/cover.jpg?player=${playerName}` 
                      }; 
      
                      this.nowPlaying.timeRemaining = this.formatTime(this.nowPlaying.duration - this.nowPlaying.position);
      
                      this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', this.nowPlaying); 
      
                  } catch (err) {
                      console.error(`MMM-LyrionNowPlaying: Error parsing Lyrion API response: ${err}`);
                      this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', { error: `Error parsing Lyrion API response: ${err}` });
                  }
              });
          },
      
          formatTime: function(seconds) {
              const minutes = Math.floor(seconds / 60);
              const remainingSeconds = seconds % 60;
              return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
          }
      });
      
      
      posted in Troubleshooting
      H
      hokie-bird
    • RE: DIY Module Displays Nothing

      Thanks to all for the suggestions. Ive attempted to incorporate them all, which has yeilded a small bit of progress: now 'No song is playing" appears bottom_center at MM startup for a second or 2, then vanishes nothing displaying again regardless of whether music starts, stops, etc. Browser console still reports data being received, and I cant figure how else to use the Developer Tools to troubleshoot. Here’s the latest code:

      MMM-LyrionNowPlaying.js

      /* MagicMirror² Module: MMM-LyrionNowPlaying */
      
      Module.register("MMM-LyrionNowPlaying", {
      
          // Default module config.
          defaults: {
              updateInterval: 1000,
              retryDelay: 2500,
              lyrionServer: 'http://localhost:9000',
              playerName: 'livingroom-mm',
              showCoverArt: true,
              coverArtSize: 150,
              fadeSpeed: 4000,
          },
      
          getStyles: function () {
              return ["MMM-LyrionNowPlaying.css"];
          },
      
          start: function () {
              Log.info("Starting module: " + this.name);
              this.nowPlaying = {
                  artist: "",
                  song: "",
                  timeRemaining: "",
                  coverArt: ""
              };
              this.isPlaying = false;
              this.updateTimer = null; // Initialize updateTimer
      
              this.updateDom(0);
              this.scheduleUpdate();
          },
      
          notificationReceived: function (notification, payload, sender) {
              if (notification === "ALL_MODULES_STARTED" || notification === "DOM_OBJECTS_CREATED") {
                  this.sendSocketNotification('GET_LYRION_NOW_PLAYING', {
                      lyrionServer: this.config.lyrionServer,
                      playerName: this.config.playerName
                  });
              }
          },
      
          getDom: function () {
              const wrapper = document.createElement("div");
              wrapper.classList.add("wrapper");
      
              if (this.isPlaying) {
                  if (this.nowPlaying.coverArt && this.config.showCoverArt) {
                      const coverArtImg = document.createElement("img");
                      coverArtImg.src = this.nowPlaying.coverArt;
                      coverArtImg.width = this.config.coverArtSize;
                      coverArtImg.height = this.config.coverArtSize;
                      coverArtImg.classList.add("coverArt");
                      wrapper.appendChild(coverArtImg);
                  }
      
                  const infoContainer = document.createElement("div");
                  infoContainer.classList.add("infoContainer");
      
                  if (this.nowPlaying.artist && this.nowPlaying.song) {
                      const songInfo = document.createElement("div");
                      songInfo.classList.add("songInfo");
                      songInfo.innerHTML =
                          this.nowPlaying.artist + " - " +
                          this.nowPlaying.song;
                      infoContainer.appendChild(songInfo);
                  }
      
                  if (this.nowPlaying.timeRemaining) {
                      const timeRemaining = document.createElement("div");
                      timeRemaining.classList.add("timeRemaining");
                      timeRemaining.innerHTML = "Time Remaining: " + this.nowPlaying.timeRemaining;
                      infoContainer.appendChild(timeRemaining);
                  }
      
                  wrapper.appendChild(infoContainer);
              } else {
                  wrapper.innerHTML = "No song is currently playing.";
              }
      
              console.log("Generated HTML:", wrapper.innerHTML);
              return wrapper;
          },
      
          scheduleUpdate: function () {
              if (this.updateTimer) {
                  clearInterval(this.updateTimer);
              }
      
              this.updateTimer = setInterval(() => {
                  this.getLyrionNowPlaying();
              }, this.config.updateInterval);
          },
      
          getLyrionNowPlaying: function () {
              this.sendSocketNotification('GET_LYRION_NOW_PLAYING', {
                  lyrionServer: this.config.lyrionServer,
                  playerName: this.config.playerName
              });
          },
      
          socketNotificationReceived: function (notification, payload) {
              if (notification === 'LYRION_NOW_PLAYING_RESULT') {
                  if (payload.error) {
                      Log.error(`MMM-LyrionNowPlaying: ${payload.error}`);
                  } else {
                      this.nowPlaying = payload;
                      console.log("Received data:", this.nowPlaying);
                      console.log("this.nowPlaying after update:", this.nowPlaying);
      
                      // Corrected isPlaying check:
                      this.isPlaying = (this.nowPlaying.artist && this.nowPlaying.artist !== "" && this.nowPlaying.song && this.nowPlaying.song !== "") ? true : false;
      
                      const duration = Number(this.nowPlaying.duration);
                      const position = Number(this.nowPlaying.position);
      
                      if (!isNaN(duration) && !isNaN(position) && duration > 0 && position >= 0) {
                          this.nowPlaying.timeRemaining = this.formatTime(duration - position);
                      } else {
                          this.nowPlaying.timeRemaining = "";
                      }
      
                      this.updateDom(this.config.fadeSpeed);
                  }
              }
          },
      
          formatTime: function (seconds) {
              const minutes = Math.floor(seconds / 60);
              const remainingSeconds = seconds % 60;
              return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
          }
      });
      
      

      Suggestions welcome and again a huge thank you to the community.

      posted in Troubleshooting
      H
      hokie-bird
    • DIY Module Displays Nothing

      Hi There - I’ve been working on a module to display the “Now Playing” info (song, artist, cover-art, time remaining) from a particular player of my Lyrion Music Server (formerly Logitech Media Sever) to my MM. (With alot of coding help from Google’s Gemini ai, full disclosure) .

      I have a working node_helper.js that retrieves the JSON data and parses it into the desired variables (text for song, artist and time remaining, URL for coverart ) verified via console.log messages. My LyrionNowPlaying.js is accurate communicating with node_helper.js (verified via browser console messages providing correct data for artist, title etc.) but I simply cant get the module to display anything on the actual MM. I’d be super-grateful for any insight anyone could share to help me troubleshoot, as I’m at a loss and even Gemini is giving up…

      Thanks.

      LyrionNowPlaying.js

      /* MagicMirror² Module: MMM-LyrionNowPlaying */
      
      Module.register("MMM-LyrionNowPlaying", {
      
          // Default module config.
          defaults: {
              updateInterval: 1000, // Update interval in milliseconds (default: 1 second)
              retryDelay: 2500,
              lyrionServer: 'http://localhost:9000', // Lyrion server address for JSON-RPC
              playerName: 'livingroom-mm', // Default player name
              showCoverArt: true,
              coverArtSize: 150, // Size of the cover art image
              fadeSpeed: 4000,
          },
      
          getStyles: function () {
              return ["MMM-LyrionNowPlaying.css"];
          },
      
          start: function() {
              Log.info("Starting module: " + this.name);
              this.nowPlaying = {
                  artist: "",
                  song: "",
                  timeRemaining: "",
                  coverArt: "" 
              };
              this.isPlaying = false; // Track playback state
              this.updateDom(this.config.fadeSpeed); 
              this.scheduleUpdate();
          },
      
          getDom: function() {
              const wrapper = document.createElement("div");
              wrapper.classList.add("wrapper"); 
      
              if (this.isPlaying) {
                  if (this.nowPlaying.coverArt && this.config.showCoverArt) {
                      const coverArtImg = document.createElement("img");
                      coverArtImg.src = this.nowPlaying.coverArt;
                      coverArtImg.width = this.config.coverArtSize;
                      coverArtImg.height = this.config.coverArtSize;
                      coverArtImg.classList.add("coverArt");
                      wrapper.appendChild(coverArtImg);
                  }
      
                  const infoContainer = document.createElement("div");
                  infoContainer.classList.add("infoContainer"); 
      
                  if (this.nowPlaying.artist && this.nowPlaying.song) {
                      const songInfo = document.createElement("div");
                      songInfo.classList.add("songInfo");
                      songInfo.innerHTML = 
                          this.nowPlaying.artist + " - " + 
                          this.nowPlaying.song; 
                      infoContainer.appendChild(songInfo);
                  }
      
                  if (this.nowPlaying.timeRemaining) {
                      const timeRemaining = document.createElement("div");
                      timeRemaining.classList.add("timeRemaining");
                      timeRemaining.innerHTML = "Time Remaining: " + this.nowPlaying.timeRemaining;
                      infoContainer.appendChild(timeRemaining);
                  }
      
                  wrapper.appendChild(infoContainer);
              } else {
                  wrapper.innerHTML = "No song is currently playing."; 
              }
      
              return wrapper;
          },
      
          scheduleUpdate: function() {
              setInterval(() => {
                  this.getLyrionNowPlaying();
              }, this.config.updateInterval);
          },
      
          getLyrionNowPlaying: function() {
              this.sendSocketNotification('GET_LYRION_NOW_PLAYING', {
                  lyrionServer: this.config.lyrionServer,
                  playerName: this.config.playerName
              });
          },
      
          socketNotificationReceived: function(notification, payload) {
              if (notification === 'LYRION_NOW_PLAYING_RESULT') {
                  if (payload.error) {
                      Log.error(`MMM-LyrionNowPlaying: ${payload.error}`);
                  } else {
                      this.nowPlaying = payload;
                      console.log("Received data:", this.nowPlaying); 
      
                      // Update playback state
                      this.isPlaying = (this.nowPlaying.artist && this.nowPlaying.song) ? true : false; 
      
                      // Calculate and update timeRemaining 
                      if (this.nowPlaying.duration > 0 && this.nowPlaying.position >= 0) {
                          this.nowPlaying.timeRemaining = this.formatTime(this.nowPlaying.duration - this.nowPlaying.position); 
                      } else {
                          this.nowPlaying.timeRemaining = ""; 
                      }
      
                      this.updateDom(this.config.fadeSpeed); 
                  }
              }
          },
      
          formatTime: function(seconds) {
              const minutes = Math.floor(seconds / 60);
              const remainingSeconds = seconds % 60;
              return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
          }
      });
      
      

      LyrionNowPlaying.css

      .module.MMM-LyrionNowPlaying {
          width: auto; 
          max-width: 300px; 
          background-color: rgba(255, 255, 255, 0.1); 
          border-radius: 5px; 
          padding: 10px; 
          text-align: center;
      }
      
      .coverArt {
          margin-bottom: 10px;
      }
      
      .infoContainer {
          text-align: center; 
      }
      
      .songInfo {
          font-weight: bold; 
      
      

      Relevant config.js (with correct IP and player name masked):

                      {
                              module: 'MMM-LyrionNowPlaying',
                              position: 'bottom_center',
                              config: {
                                      lyrionServer: 'http://xx.xx.xx.xx:9000', // Use port 9000 for JSON-RPC
                                      playerName: 'YYYYYYY,
                                      // Other config options 
                                      }
                      },
      
      
      posted in Troubleshooting
      H
      hokie-bird
    • RE: Default MM Font to use in iFrame?

      Thanks, and I think I understand that, so trying to make the actual source webpage that’s displaying in the iFrame match the MM font, as I can control the source webpage via its CSS. Thus my ask for clarity on which font I can use on the source page to make it match.

      posted in Requests
      H
      hokie-bird
    • Default MM Font to use in iFrame?

      I’m working on a solution to display the “Now Playing” information of my multi-room audio system on my MM. Easiest path seems to be displaying a webpage via the iFrame module. That said, I really want the metadata in the iFrame to match the rest of MM appearance/font-wise. The iFrame module does not seem to “natively” inherit the MM font, so I’m looking to hard-code the native MM font into the CSS of the webpage. Can someone provide guidance or suggestions on the name (or equivalent) of the exact font the default modules use? I’ve tried looking thru the main CSS, and find “Roboto” but when I use that font in the CSS, it doesn’t match.

      Thanks in-advance for the consideration.

      posted in Requests
      H
      hokie-bird
    • 1 / 1