« get me outta code hell

mtui - Music Text User Interface - user-friendly command line music player
about summary refs log tree commit diff
path: root/ui.js
diff options
context:
space:
mode:
Diffstat (limited to 'ui.js')
-rw-r--r--ui.js75
1 files changed, 64 insertions, 11 deletions
diff --git a/ui.js b/ui.js
index 3fbaa51..90fb13a 100644
--- a/ui.js
+++ b/ui.js
@@ -32,6 +32,7 @@ const {
 
 const fs = require('fs')
 const { promisify } = require('util')
+const readFile = promisify(fs.readFile)
 const writeFile = promisify(fs.writeFile)
 
 class AppElement extends FocusElement {
@@ -48,6 +49,9 @@ class AppElement extends FocusElement {
     this.editMode = false
 
     this.rootDirectory = process.env.HOME + '/.mtui'
+    this.metadataPath = this.rootDirectory + '/track-metadata.json'
+
+    this.loadMetadata()
 
     this.paneLeft = new Pane()
     this.addChild(this.paneLeft)
@@ -58,6 +62,10 @@ class AppElement extends FocusElement {
     this.tabber = new Tabber()
     this.paneLeft.addChild(this.tabber)
 
+    this.metadataStatusLabel = new Label()
+    this.metadataStatusLabel.visible = false
+    this.paneLeft.addChild(this.metadataStatusLabel)
+
     this.newGrouplikeListing()
 
     this.queueListingElement = new QueueListingElement(this)
@@ -287,7 +295,8 @@ class AppElement extends FocusElement {
         {label: 'Queue!', action: emitControls(false)},
         {divider: true},
 
-        {label: 'Process metadata', action: () => this.processMetadata(item)},
+        {label: 'Process metadata (new entries)', action: () => this.processMetadata(item, false)},
+        {label: 'Process metadata (reprocess)', action: () => this.processMetadata(item, true)},
         {label: 'Remove from queue', action: () => this.unqueueGrouplikeItem(item)}
       ]
     }
@@ -391,7 +400,14 @@ class AppElement extends FocusElement {
     this.playbackPane.h = this.contentH - this.playbackPane.y
 
     this.tabber.fillParent()
+
+    if (this.metadataStatusLabel.visible) {
+      this.tabber.h--
+      this.metadataStatusLabel.y = this.paneLeft.contentH - 1
+    }
+
     this.tabber.fixLayout()
+
     this.queueListingElement.fillParent()
     this.playbackInfoElement.fillParent()
   }
@@ -872,19 +888,56 @@ class AppElement extends FocusElement {
     this.playbackInfoElement.clearInfo()
   }
 
-  processMetadata(item) {
-    if (isGroup(item)) {
-      return Promise.all(item.items.map(x => this.processMetadata(x)))
+  async readMetadata() {
+    try {
+      return JSON.parse(await readFile(this.metadataPath))
+    } catch (error) {
+      // Just stop. It's okay to fail to load metadata.
+      return null
     }
+  }
 
-    return this.throttleMetadata(async () => {
-      const filePath = await this.downloadGrouplikeItem(item)
-      const metadataReader = getMetadataReaderFor(filePath)
-      const data = await metadataReader(filePath)
+  async loadMetadata() {
+    Object.assign(this.metadataDictionary, await this.readMetadata())
+  }
 
-      this.metadataDictionary[item.downloaderArg] = filePath
-      this.metadataDictionary[filePath] = data
-    })
+  async saveMetadata() {
+    const newData = Object.assign({}, await this.readMetadata(), this.metadataDictionary)
+    await writeFile(this.metadataPath, JSON.stringify(newData))
+  }
+
+  async processMetadata(item, reprocess = false, top = true) {
+    if (top) {
+      this.metadataStatusLabel.text = 'Processing metadata...'
+      this.metadataStatusLabel.visible = true
+      this.fixLayout()
+    }
+
+    if (isGroup(item)) {
+      await Promise.all(item.items.map(x => this.processMetadata(x, reprocess, false)))
+    } else {
+      if (!reprocess && this.getMetadataFor(item)) {
+        return
+      }
+
+      await this.throttleMetadata(async () => {
+        const filePath = await this.downloadGrouplikeItem(item)
+        const metadataReader = getMetadataReaderFor(filePath)
+        const data = await metadataReader(filePath)
+
+        this.metadataDictionary[item.downloaderArg] = filePath
+        this.metadataDictionary[filePath] = data
+      })
+
+      this.metadataStatusLabel.text = `Processing metadata - ${this.throttleMetadata.queue.length} to go.`
+    }
+
+    if (top) {
+      this.metadataStatusLabel.text = ''
+      this.metadataStatusLabel.visible = false
+      this.fixLayout()
+      await this.saveMetadata()
+    }
   }
 
   getMetadataFor(item) {