• Recent
  • Tags
  • Unsolved
  • Solved
  • MagicMirror² Repository
  • Documentation
  • 3rd-Party-Modules
  • Donate
  • Discord
  • Register
  • Login
MagicMirror Forum
  • Recent
  • Tags
  • Unsolved
  • Solved
  • MagicMirror² Repository
  • Documentation
  • 3rd-Party-Modules
  • Donate
  • Discord
  • Register
  • Login
A New Chapter for MagicMirror: The Community Takes the Lead
Read the statement by Michael Teeuw here.

Airplay 'Now Playing' module - help badly needed

Scheduled Pinned Locked Moved Development
16 Posts 8 Posters 11.9k Views 9 Watching
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    darrene
    last edited by Oct 25, 2016, 5:01 PM

    I’ve really been struggling to write my first module.

    I’ve used Shairport-Sync to allow my mirror to act as an Airplay device - something which works a treat.
    I’ve added Shairport-Sync-Metadata-Reader in order to base64-decode the playing track metadata, which Shairport outputs in xml format to a FiFo file.

    What I’m trying to do is create a module to read the FiFo stream, base64-decode the values and it sees, and display a couple of the fields (Artist/Track)

    I think I’ll need a node-helper to do the watch/decode/filter and then send any Artist & Track fields it sees to the module which then displays it.

    I’ve created this which pops up the decoded result for a hardcoded string

    <script>
    var string = 'RGFycmVu';
    var decodedString = atob(string);
    window.alert(decodedString);
    </script>
    

    I’ve tried without success though to incoporate this as a function into a .js file, so that I can display my test-decode on the mirror.
    I’ve been looking through all the modules I can find to find something I can use as an example but no luck. I know I need to pass the decodedString variable somehow but have struggled to work out how :(

    1 Reply Last reply Reply Quote 0
    • D Offline
      darrene
      last edited by Oct 26, 2016, 9:53 PM

      The first step of my module, which simply displays a base64-decoded string in the mirror reads like this.

      /* global Module */
      /* Magic Mirror
      * Module: base64
      *
      * By Michael Teeuw http://michaelteeuw.nl
      * MIT Licensed.
      */
      
      Module.register("base64",{
      
          // Default module config.
          defaults: {
                  text: "Hello World!"
          },
      
      
        frombase64: function() {
          var string = 'RGFycmVu';
          var decodedString = atob(string);
          return decodedString;
          },
      
          // Override dom generator.
          getDom: function() {
                  var wrapper = document.createElement("div");
                  var decstr = this.frombase64
                  var msgstr = document.createTextNode(decstr);
                  wrapper.appendChild(msgstr);
                  return wrapper;
          }
      });
      

      It seems like it should work, but I get a literal string rather than a value returned…
      0_1477518803379_mm.jpg

      A 1 Reply Last reply Oct 27, 2016, 2:35 AM Reply Quote 0
      • A Offline
        alexyak @darrene
        last edited by Oct 27, 2016, 2:35 AM

        @darrene You’re missing parenthesis in your call to frombase64:

        this.frombase64();

        D 1 Reply Last reply Oct 27, 2016, 8:19 AM Reply Quote 3
        • D Offline
          darrene @alexyak
          last edited by Oct 27, 2016, 8:19 AM

          Ah! Thanks so much @alexyak - that’s fantastic. I can now move forwards :)

          So parenthesis are needed to call the function and explicitly not pass it a parameter. Is that right?

          1 Reply Last reply Reply Quote 0
          • D Offline
            darrene
            last edited by darrene Oct 27, 2016, 8:11 PM Oct 27, 2016, 8:11 PM

            So step 2, I have made a short javascript file that will read a fifo file and decode what it sees in the buffer.

            var fs = require('fs')
            var fifo = fs.createReadStream('shairport-sync-metadata')
            fifo.on('data', function(fifoHexBuffer) {
                fifoHexBuffer = fifoHexBuffer.toString();
                console.log(fifoHexBuffer)    
            })
            

            At the moment, the code runs once and stops once it reads. My next task is to have it continue, then I’ll have to make it into a node-helper script, to interact with my base64 decoder/display

            S 1 Reply Last reply Oct 27, 2016, 8:27 PM Reply Quote 0
            • S Offline
              strawberry 3.141 Project Sponsor Module Developer @darrene
              last edited by Oct 27, 2016, 8:27 PM

              @darrene checkout the file watcher of the nodejs filesystem https://nodejs.org/docs/latest/api/fs.html#fs_class_fs_fswatcher

              Please create a github issue if you need help, so I can keep track

              1 Reply Last reply Reply Quote 1
              • D Offline
                darrene
                last edited by Oct 28, 2016, 5:34 PM

                Luckily there is a fifo-js package available, which makes things super-easy!
                npm install fifo-js

                const FIFO = require('fifo-js')
                
                let fifo = new FIFO('fifo-testfile')
                
                var count = 1
                while (count == 1)
                    {
                    let text = fifo.readSync(fifo)
                    console.log(text)
                    }
                fifo.close()
                

                I’m getting there. I have an IN and I have an OUT in javascript. Now the hard work of joining the two together - interpreting and the decoding the appropriate metadata begins!

                1 Reply Last reply Reply Quote 0
                • D Offline
                  darrene
                  last edited by darrene Oct 28, 2016, 11:01 PM Oct 28, 2016, 10:34 PM

                  So a bit more testing and things aren’t looking as rosy as I’d first thought. Before trying fifo-js, I’d experimented with the filesystem readStream - If i try looping that I end up with a java out of memory condition.

                  The fifo-js approach works with a fifo file that I echo things into to test, but doesn’t return anything while the Shairport service has it open for some reason?

                  There is a metadata reader script which I could use to read the metadata and parse it. I’ve compiled the executable and it runs fine. I should be able to call that from my javascript module through child process, right?

                  1 Reply Last reply Reply Quote 0
                  • D Offline
                    darrene
                    last edited by Oct 29, 2016, 12:04 PM

                    Hmm, using a child process doesn’t return anything either :(

                    The shairport metadata reader is a compiled C program which uses printf to return the metadata to the console:

                    pi@raspberrypi:~/fifo-js $ ~/shairport-sync-metadata-reader/shairport-sync-metadata-reader < /tmp/shairport-sync-metadata
                    
                    Artist: "Sohn".
                    Title: "Tremors".
                    
                    ^C
                    pi@raspberrypi:~/fifo-js $ 
                    

                    But I dont’ seem to be able to parse what’s being sent to stdout from my javascript

                    If anyone has any examples that work, I’d be grateful.

                    J 1 Reply Last reply Dec 13, 2016, 3:52 AM Reply Quote 0
                    • J Offline
                      jdfraser @darrene
                      last edited by Dec 13, 2016, 3:52 AM

                      Hi @darrene ,

                      How did you ever make out with your module? I’ve started down the same path, I’m also using shairport-sync but in conjunction with forked-daapd (an airplay server for Raspbian).

                      As forked-daapd can also use mpd commands I’ve been trying to use komponist, which I’ve managed to make return the playing song, album, etc. print out to the console but as I’ve never really done any javascript before am trying to piece together building a module for MM.

                      If you’ve made any progress on your module, I’d love to see it as it may help me finish mine.

                      1 Reply Last reply Reply Quote 1
                      • 1
                      • 2
                      • 1 / 2
                      • First post
                        Last post
                      Enjoying MagicMirror? Please consider a donation!
                      MagicMirror created by Michael Teeuw.
                      Forum managed by Sam, technical setup by Karsten.
                      This forum is using NodeBB as its core | Contributors
                      Contact | Privacy Policy