commit a11df5e599e0be88845c5edcdda131c268313fab
Author: David Sorber <david.sorber@gmail.com>
Date:   Mon Jan 7 17:43:35 2019 -0500

    It works! Need to add some polish before we're ready to call it 0.1, but
    nearly there!

diff --git a/software/hbkcd/hbkcd/config.py b/software/hbkcd/hbkcd/config.py
index bfcb5cc..921e2b4 100644
--- a/software/hbkcd/hbkcd/config.py
+++ b/software/hbkcd/hbkcd/config.py
@@ -11,13 +11,19 @@ DEFAULT_LOG_LEVEL = logging.DEBUG
 # Absolute path the to the HandbrakeCLI executable
 HANDBRAKE_PATH = '/opt/local/bin/HandBrakeCLI'
 
+HANDBRAKE_CMD = [HANDBRAKE_PATH, '-i', '', '-o', '/home/dsorber/clip-OUT.mkv', 
+                 '-f', 'av_mkv', '-e', 'x265', '--encoder-preset', 'veryslow', 
+                 '--encoder-level', 'auto', '-q', '24', '-2', '-T', '-r', 
+                 '23.98', '-E', 'copy:aac']
+
 # Absolute path to the ffprobe executable
 FFPROBE_PATH = '/home/dsorber/ffprobe'
 
 # The ffprobe command used to get information about the video file
-FFPROBE_CMD = '{:s} -show_streams -show_entries stream=width,height,'\
-              'display_aspect_ratio,r_frame_rate,bit_rate,codec_type,'\
-              'codec_name -of json -v quiet -i "{:s}"'
+FFPROBE_CMD = [FFPROBE_PATH, '-show_streams', '-show_entries', 
+               'stream=width,height,display_aspect_ratio,r_frame_rate,'
+               'bit_rate,codec_type,codec_name', '-of', 'json', '-v', 'quiet', 
+               '-i', '']
 
 # Command server port
 COMMAND_SERVER_PORT = 8081
diff --git a/software/hbkcd/hbkcd/daemon.py b/software/hbkcd/hbkcd/daemon.py
index f15bf25..e6bd852 100755
--- a/software/hbkcd/hbkcd/daemon.py
+++ b/software/hbkcd/hbkcd/daemon.py
@@ -1,13 +1,15 @@
 #!/usr/bin/python3
+import datetime
 import logging
 import os
+import subprocess
 import sys
 import threading
 import time
 
 from hbkcd.config import *
 from hbkcd.command_server import StoppableHTTPServer, CommandHandler
-# ~ from hbkcd.queue import ENCODE_QUEUE
+from hbkcd.queue import ENCODE_QUEUE
 
 #
 # HbkCD - Handbrake Control Daemon
@@ -71,6 +73,52 @@ def main():
     try:
         while True:
             time.sleep(1)
+            item = ENCODE_QUEUE.get_next()
+            if item is None:
+                continue
+                
+            # Mark next item as in progress
+            item.in_progress = True
+            item.encode_started = datetime.datetime.now()
+            
+            # Start Handbrake process
+            cmd = HANDBRAKE_CMD
+            cmd[2] = item.path
+            
+            hbk_proc = subprocess.Popen(cmd, 
+                                        stderr=subprocess.PIPE, 
+                                        stdout=subprocess.PIPE, 
+                                        encoding='utf-8')
+    
+            # Create an interator to the stdout of the process so we can 
+            # monitor status
+            proc_stdout = iter(hbk_proc.stdout.readline, '')            
+            status_thread = threading.Thread(target=item.update_status, 
+                                             args=(proc_stdout,))
+            status_thread.start()
+            
+            # Let the HandBrake process run and print a message to the log
+            # every minute
+            ctr = 0
+            while hbk_proc.poll() is None:
+                ctr += 1
+                if ctr % 60 == 0:
+                    logging.info('Encode in progress... {:s}'.format(ctr, item.status))
+                    ctr = 0
+                time.sleep(1)
+            
+            item.encode_finished = datetime.datetime.now()
+            status_thread.join()
+            item.in_progress = False
+            
+            if hbk_proc.returncode == 0:
+                logging.info('Encode of {:s} completed!'.format(item.path))
+            else:
+                logging.error('Error while encoding {:s}'.format(item.path))
+            
+            # Remove the item from the queue
+            ENCODE_QUEUE.remove(0)
+            
     except KeyboardInterrupt:
         logging.warn('Command server interrupted')
     finally:
diff --git a/software/hbkcd/hbkcd/queue.py b/software/hbkcd/hbkcd/queue.py
index 01df141..ba72022 100644
--- a/software/hbkcd/hbkcd/queue.py
+++ b/software/hbkcd/hbkcd/queue.py
@@ -30,14 +30,37 @@ class EncodeQueue(object):
         item.position = position
             
     def remove(self, idx):
-        # TODO: implement removal
-        pass
+        if idx >= len(self.queue):
+            logging.error('Invalid index: {:d}'.format(idx))
+            return False
+            
+        if self.queue[idx].in_progress:
+            logging.error('Unable to remove index {:d}; encode in progress'
+                          .format(idx))
+            return False
+            
+        logging.debug('Removing index: {:d}'.format(idx))
+        self.queue.pop(idx)
+        
+        # Re-set positions for all items
+        ctr = 1
+        for item in self.queue[]
+            item.position = ctr
+            ctr += 1
+        
+        return True
         
     def get_list(self):
         """ Get queue as a list of dicts that can be converted to JSON easily
         """
         return [item.get_dict_rep() for item in self.queue]
         
+    def get_next(self):
+        if not self.queue:
+            return None
+        else:
+            return self.queue[0]
+            
 
 class QueueItem(object):
 
@@ -46,6 +69,7 @@ class QueueItem(object):
         self.filename = os.path.basename(path)
         self.position = None
         self.in_progress = False
+        self.status = 'queued'
         
         # Video
         self.width = None
@@ -63,8 +87,10 @@ class QueueItem(object):
         
     def probe(self):
         # Fill in ffprobe command
-        cmd = FFPROBE_CMD.format(FFPROBE_PATH, self.path)
-        proc = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, 
+        cmd = FFPROBE_CMD
+        cmd[9] = self.path
+        proc = subprocess.run(cmd, 
+                              stdout=subprocess.PIPE, 
                               stderr=subprocess.PIPE)
         
         probe_okay = True
@@ -106,6 +132,7 @@ class QueueItem(object):
         return {'position':         self.position,
                 'path':             self.path,
                 'in_progress':      self.in_progress,
+                'status':           self.status,
                 'width':            self.width,
                 'height':           self.height,
                 'framerate':        self.framerate,
@@ -114,6 +141,16 @@ class QueueItem(object):
                 'encode_started':   format_ds(self.encode_started),
                 'encode_finished':  format_ds(self.encode_finished)}
 
+    def update_status(self, stdout_iter):
+        logging.info('Update status thread running for: {:s}'.format(self.path))
+        for stdout_line in stdout_iter:
+            # Naturally this is very specific parsing for the HBK output
+            try:
+                self.status = stdout_line.strip().split(',', 1)[1].strip()
+            except IndexError:
+                self.status = stdout_line
+        logging.info('Update status thread terminating')
+
 
 # Does this need to be protected?
 ENCODE_QUEUE = EncodeQueue()
diff --git a/software/hbkcd/setup.py b/software/hbkcd/setup.py
index 94b7238..ac53e7c 100755
--- a/software/hbkcd/setup.py
+++ b/software/hbkcd/setup.py
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
 
 setup(
     name = 'hbkcd',
-    version = '0.0.2',
+    version = '0.0.3',
     description = 'HandBrake Control Daemon',
     packages = find_packages(),
     python_requires = '>=3.6.0',
