Zachary Kotlarek 14 years ago
parent
commit
9bd21a2e56

+ 0 - 1
amplifier/amplifier.pl

@@ -1 +0,0 @@
-../serial/serial.pl

+ 0 - 98
amplifier/amplifierPower.pl

@@ -1,98 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-use IO::Socket::UNIX;
-use POSIX qw(ceil floor);
-
-# App config
-my $DELAY    = 5;
-my $TIMEOUT  = 5;
-my $TEMP_DIR = `getconf DARWIN_USER_TEMP_DIR`;
-chomp($TEMP_DIR);
-my $DATA_DIR = $TEMP_DIR . 'plexMonitor/';
-my $CMD_FILE = $DATA_DIR . 'AMPLIFIER.socket';
-
-# Debug
-my $DEBUG = 0;
-if ($ENV{'DEBUG'}) {
-	$DEBUG = 1;
-}
-
-# Sanity check
-if (!-d $DATA_DIR || !-S $CMD_FILE) {
-	die("Bad config\n");
-}
-
-# Socket init
-my $sock = IO::Socket::UNIX->new(
-	'Peer'    => $CMD_FILE,
-	'Type'    => SOCK_DGRAM,
-	'Timeout' => $TIMEOUT
-) or die('Unable to open socket: ' . $CMD_FILE . ": ${@}\n");
-
-# State
-my $state     = 'INIT';
-my $stateLast = $state;
-my $projector = 0;
-
-# Loop forever
-while (1) {
-
-	# Monitor the PROJECTOR file for state only
-	{
-		$projector = 0;
-		my $fh;
-		open($fh, $DATA_DIR . 'PROJECTOR')
-		  or die("Unable to open PROJECTOR\n");
-		my $text = <$fh>;
-		close($fh);
-		if ($text =~ /1/) {
-			$projector = 1;
-		}
-		if ($DEBUG) {
-			print STDERR 'Projector: ' . $projector . "\n";
-		}
-	}
-
-	# Monitor the AMPLIFIER file for state only
-	{
-		$stateLast = 'OFF';
-		my $fh;
-		open($fh, $DATA_DIR . 'AMPLIFIER')
-		  or die("Unable to open AMPLIFIER\n");
-		my $text = <$fh>;
-		close($fh);
-		if ($text =~ /1/) {
-			$stateLast = 'ON';
-		}
-		if ($DEBUG) {
-			print STDERR 'Amplifier: ' . $stateLast . "\n";
-		}
-	}
-
-	# Calculate the new state -- track the projector power state
-	if ($projector) {
-		$state = 'ON';
-	} else {
-		$state = 'OFF';
-	}
-
-	# If the state changed, do something about if
-	if ($state ne $stateLast) {
-		if ($DEBUG) {
-			print STDERR 'State change: ' . $stateLast . ' => ' . $state . "\n";
-		}
-		if ($state eq 'OFF' || $state eq 'ON') {
-			$sock->send($state)
-			  or die('Unable to write command to socket: ' . $CMD_FILE . ': ' . $state . ": ${!}\n");
-		}
-	}
-
-	# Wait and loop
-	sleep($DELAY);
-}
-
-# Cleanup
-$sock->close();
-undef($sock);
-exit(0);

+ 0 - 29
amplifier/launchd/com.uberzach.amplifier.plist

@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>UserName</key>
-	<string>tv</string>
-	<key>LimitLoadToHosts</key>
-	<array>
-		<string>heady.uberzach.com</string>
-	</array>
-	<key>RunAtLoad</key>
-	<true/>
-	<key>Label</key>
-	<string>com.uberzach.amplifier</string>
-	<key>KeepAlive</key>
-	<dict>
-		<key>PathState</key>
-		<dict>
-			<key>/dev/tty.Amplifier-DevB</key>
-			<true/>
-		</dict>
-	</dict>
-	<key>ProgramArguments</key>
-	<array>
-		<string>/Users/tv/bin/video/amplifier/amplifier.pl</string>
-		<string>15</string>
-	</array>
-</dict>
-</plist>

+ 0 - 28
amplifier/launchd/com.uberzach.amplifier.power.plist

@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>UserName</key>
-	<string>tv</string>
-	<key>LimitLoadToHosts</key>
-	<array>
-		<string>heady.uberzach.com</string>
-	</array>
-	<key>RunAtLoad</key>
-	<true/>
-	<key>Label</key>
-	<string>com.uberzach.amplifier.power</string>
-	<key>KeepAlive</key>
-	<dict>
-		<key>OtherJobEnabled</key>
-		<dict>
-			<key>com.uberzach.amplifier</key>
-			<true/>
-		</dict>
-	</dict>
-	<key>ProgramArguments</key>
-	<array>
-		<string>/Users/tv/bin/video/amplifier/amplifierPower.pl</string>
-	</array>
-</dict>
-</plist>

+ 0 - 1
dmx/cmd.pl

@@ -1 +0,0 @@
-../serial/cmd.pl

+ 0 - 1
dmx/dimChannels.py

@@ -1 +0,0 @@
-setChannels.py

+ 0 - 126
dmx/dmx.pl

@@ -1,126 +0,0 @@
-#!/opt/local/bin/python2.7
-
-# Append the path to help find our OLA packages
-import sys
-sys.path.append('/opt/local/lib/python2.7/site-packages')
-sys.path.append('/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages')
-
-import os
-import array
-import select
-import socket
-import string
-import subprocess
-from ola.ClientWrapper import ClientWrapper
-
-# ====================================
-# Globals
-# ====================================
-max_channels = 512
-wrapper = None
-state = [ 0 ] * max_channels
-cmds = { 'value' : [ 0 ] * max_channels, 'ticks' : [ 0 ] * max_channels }
-sock = None
-max_mesg_len = 1024
-
-# ====================================
-# Defaults
-# ====================================
-interval = 50
-universe = 0
-
-# ====================================
-# Wrapper callback -- exit on errors
-# ====================================
-def DmxSent(state):
-  # Stop on errors
-  if not state.Succeeded():
-    wrapper.Stop()
-
-# ====================================
-# Main calculation
-# ====================================
-def SendDMXFrame():
-  # Re-schedule ourselves in interval ms (do this first to keep the timing consistent)
-  wrapper.AddEvent(interval, SendDMXFrame)
-  
-  # Check for new commands
-  
-  ready = select.select([sock], [], [], interval / 2000)[0]
-  for fh in ready:
-    cmd = fh.recvfrom(max_mesg_len)[0]
-    channel, duration, intensity = string.split(cmd, ':')
-    try:
-      channel = int(channel)
-      duration = int(duration)
-      intensity = int(intensity)
-    except ValueError:
-      print 'Invalid command:', cmd
-      channel = -1
-    if (channel >= 0 and channel <= 512 and intensity >= 0 and intensity <= 255 and duration >= 0 and duration <= 60000):
-      if (channel > 0):
-        cmds['value'][channel - 1] = intensity
-        cmds['ticks'][channel - 1] = duration / interval
-      else:
-        for i in range(len(state)):
-          cmds['value'][i] = intensity
-          cmds['ticks'][i] = duration / interval
-    else:
-      print 'Invalid command parameters:', channel, duration, intensity
-  
-  # Update values for each channel
-  for i in range(len(cmds['value'])):
-    if (cmds['value'][i] != state[i]):
-      diff = cmds['value'][i] - state[i]
-      if (cmds['ticks'][i] < 1):
-        delta = diff
-      else:
-        delta = float(diff) / float(cmds['ticks'][i])
-      state[i] += int(delta)
-      cmds['ticks'][i] -= 1
-    
-  # Send all DMX channels
-  data = array.array('B')
-  for i in range(len(state)):
-    data.append(state[i])
-  wrapper.Client().SendDmx(universe, data, DmxSent)
-
-# ====================================
-# Main
-# ====================================
-
-# Pick a universe (default from above, or as specified in the environment)
-if 'UNIVERSE' in os.environ:
-  universe = int(os.environ['UNIVERSE'])
-
-# Pick a tick interval (default from above, or as specified in the environment)
-if 'INTERVAL' in os.environ:
-  universe = int(os.environ['INTERVAL'])
-
-# Pick a socket file ($TMPDIR/plexMonitor/DMX.socket, or as specified in the environment)
-cmd_file = None
-data_dir = None
-if 'SOCKET' in os.environ:
-  cmd_file = os.environ['SOCKET']
-  data_dir = os.dirname(cmd_file)
-else:
-  proc = subprocess.Popen(['getconf', 'DARWIN_USER_TEMP_DIR'], stdout=subprocess.PIPE, shell=False)
-  (tmp_dir, err) = proc.communicate()
-  tmp_dir = tmp_dir.strip()
-  data_dir = tmp_dir + 'plexMonitor/'
-  cmd_file = data_dir + 'DMX.socket'
-
-# Sanity checks
-if (not os.path.isdir(data_dir)):
-  raise Exception('Bad config: ' + data_dir)
-
-# Open the socket
-if (os.path.exists(cmd_file)):
-  os.unlink(cmd_file)
-sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
-sock.bind(cmd_file)
-
-# Start the DMX loop
-wrapper = ClientWrapper()
-wrapper.AddEvent(interval, SendDMXFrame)
-wrapper.Run()

+ 0 - 28
dmx/launchd/com.uberzach.ola.dmx.plist

@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>UserName</key>
-	<string>tv</string>
-	<key>LimitLoadToHosts</key>
-	<array>
-		<string>heady.uberzach.com</string>
-	</array>
-	<key>RunAtLoad</key>
-	<true/>
-	<key>Label</key>
-	<string>com.uberzach.ola.dmx</string>
-	<key>KeepAlive</key>
-	<dict>
-		<key>OtherJobEnabled</key>
-		<dict>
-			<key>com.uberzach.ola</key>
-			<true/>
-		</dict>
-	</dict>
-	<key>ProgramArguments</key>
-	<array>
-		<string>/Users/tv/bin/video/dmx/dmx.pl</string>
-	</array>
-</dict>
-</plist>

+ 0 - 31
dmx/launchd/com.uberzach.ola.plist

@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>UserName</key>
-	<string>tv</string>
-	<key>LimitLoadToHosts</key>
-	<array>
-		<string>heady.uberzach.com</string>
-	</array>
-	<key>RunAtLoad</key>
-	<true/>
-	<key>Label</key>
-	<string>com.uberzach.ola</string>
-	<key>KeepAlive</key>
-	<dict>
-		<key>PathState</key>
-		<dict>
-			<key>/dev/tty.usbserial-EN099597</key>
-			<true/>
-		</dict>
-	</dict>
-	<key>ProgramArguments</key>
-	<array>
-		<string>/opt/local/bin/olad</string>
-		<string>-s</string>
-		<string>-i</string>
-		<string>127.0.0.1</string>
-	</array>
-</dict>
-</plist>

+ 0 - 31
dmx/launchd/com.uberzach.ola.rope.plist

@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>UserName</key>
-	<string>tv</string>
-	<key>LimitLoadToHosts</key>
-	<array>
-		<string>heady.uberzach.com</string>
-	</array>
-	<key>RunAtLoad</key>
-	<true/>
-	<key>Label</key>
-	<string>com.uberzach.ola.rope</string>
-	<key>KeepAlive</key>
-	<dict>
-		<key>OtherJobEnabled</key>
-		<dict>
-			<key>com.uberzach.ola.dmx</key>
-			<true/>
-			<key>com.uberzach.projector</key>
-			<true/>
-		</dict>
-	</dict>
-	<key>ProgramArguments</key>
-	<array>
-		<string>/Users/tv/bin/video/dmx/rope.pl</string>
-		<string>0.25</string>
-	</array>
-</dict>
-</plist>

+ 0 - 262
dmx/rope.pl

@@ -1,262 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-use IO::Socket;
-use Time::HiRes qw( usleep );
-use File::Temp qw( tempfile );
-
-# Prototypes
-sub mtime($);
-sub dim($$$);
-
-# Channels:
-#	0 => All channels
-#	1 => Couch-side hidden
-#	2 => Couch-side exposed
-#	3 => Stairs
-#	4 => <Unused>
-#	5 => Bar-side hidden
-#	6 => Bar-side bar-shelves
-#	7 => Bar-side exposed
-#	8 => Bar-side ceiling
-
-# User config
-my %DIM = (
-	'OFF'    => [
-		{ 'channel' => 0, 'value' => 0,   'time' => 60000 }
-	],
-	'PLAY'      => [
-		{ 'channel' => 1, 'value' => 64,  'time' => 500   },
-		{ 'channel' => 2, 'value' => 32,  'time' => 500   },
-		{ 'channel' => 3, 'value' => 80,  'time' => 1500  },
-		{ 'channel' => 5, 'value' => 64,  'time' => 500   },
-		{ 'channel' => 6, 'value' => 36,  'time' => 500   },
-		{ 'channel' => 7, 'value' => 32,  'time' => 500   },
-		{ 'channel' => 8, 'value' => 16,  'time' => 500   },
-	],
-	'PLAY_HIGH' => [
-		{ 'channel' => 1, 'value' => 255, 'time' => 500   },
-		{ 'channel' => 2, 'value' => 128, 'time' => 500   },
-		{ 'channel' => 3, 'value' => 192, 'time' => 1500  },
-		{ 'channel' => 5, 'value' => 128, 'time' => 500   },
-		{ 'channel' => 6, 'value' => 36,  'time' => 500   },
-		{ 'channel' => 7, 'value' => 128, 'time' => 500   },
-		{ 'channel' => 8, 'value' => 16,  'time' => 500   },
-	],
-	'PAUSE'     => [
-		{ 'channel' => 1, 'value' => 255, 'time' => 1000  },
-		{ 'channel' => 2, 'value' => 192, 'time' => 10000 },
-		{ 'channel' => 3, 'value' => 192, 'time' => 5000  },
-		{ 'channel' => 5, 'value' => 255, 'time' => 1000  },
-		{ 'channel' => 6, 'value' => 104, 'time' => 12000 },
-		{ 'channel' => 7, 'value' => 192, 'time' => 10000 },
-		{ 'channel' => 8, 'value' => 92,  'time' => 16000 },
-	],
-	'MOTION'    => [
-		{ 'channel' => 1, 'value' => 255, 'time' => 1000  },
-		{ 'channel' => 2, 'value' => 192, 'time' => 1000  },
-		{ 'channel' => 3, 'value' => 192, 'time' => 1000  },
-		{ 'channel' => 5, 'value' => 192, 'time' => 1000  },
-		{ 'channel' => 6, 'value' => 104, 'time' => 1000  },
-		{ 'channel' => 7, 'value' => 192, 'time' => 1000  },
-		{ 'channel' => 8, 'value' => 92,  'time' => 1000  },
-	],
-);
-my $TIMEOUT = 180;
-
-# App config
-my $SOCK_TIMEOUT = 5;
-my $TEMP_DIR     = `getconf DARWIN_USER_TEMP_DIR`;
-chomp($TEMP_DIR);
-my $DATA_DIR = $TEMP_DIR . 'plexMonitor/';
-my $CMD_FILE = $DATA_DIR . 'DMX.socket';
-
-# Debug
-my $DEBUG = 0;
-if ($ENV{'DEBUG'}) {
-	$DEBUG = 1;
-}
-
-# Command-line arguments
-my ($DELAY) = @ARGV;
-if (!$DELAY) {
-	$DELAY = 0.5;
-}
-$DELAY *= 1000000;    # Microseconds;
-
-# Sanity check
-if (!-d $DATA_DIR || !-S $CMD_FILE) {
-	die("Bad config\n");
-}
-
-# Socket init
-my $sock = IO::Socket::UNIX->new(
-	'Peer'    => $CMD_FILE,
-	'Type'    => SOCK_DGRAM,
-	'Timeout' => $SOCK_TIMEOUT
-) or die('Unable to open socket: ' . $CMD_FILE . ": ${@}\n");
-
-# State
-my $state      = 'INIT';
-my $stateLast  = $state;
-my $playing    = 0;
-my $projector  = 0;
-my $lights     = 0;
-my $updateLast = 0;
-
-# Always force lights out at launch
-dim(0, 0, 0);
-
-# Loop forever
-while (1) {
-
-	# Monitor the PLAY_STATUS file for changes and state
-	{
-		my $mtime = mtime($DATA_DIR . 'PLAY_STATUS');
-		if ($mtime > $updateLast) {
-			$updateLast = $mtime;
-		}
-
-		# Grab the PLAY_STATUS value
-		$playing = 0;
-		my $fh;
-		open($fh, $DATA_DIR . 'PLAY_STATUS')
-		  or die("Unable to open PLAY_STATUS\n");
-		my $text = <$fh>;
-		close($fh);
-		if ($text =~ /1/) {
-			$playing = 1;
-		}
-		if ($DEBUG) {
-			print STDERR 'Playing: ' . $playing . "\n";
-		}
-	}
-
-	# Monitor the PROJECTOR file for changes and state
-	{
-		my $mtime = mtime($DATA_DIR . 'PROJECTOR');
-		if ($mtime > $updateLast) {
-			$updateLast = $mtime;
-		}
-
-		# Grab the PROJECTOR value
-		$projector = 0;
-		my $fh;
-		open($fh, $DATA_DIR . 'PROJECTOR')
-		  or die("Unable to open PROJECTOR\n");
-		my $text = <$fh>;
-		close($fh);
-		if ($text =~ /1/) {
-			$projector = 1;
-		}
-		if ($DEBUG) {
-			print STDERR 'Projector: ' . $projector . "\n";
-		}
-	}
-
-	# Monitor the LIGHTS file for presence
-	{
-		$lights = 0;
-		if (-e $DATA_DIR . 'LIGHTS') {
-			$lights = 1;
-		}
-		if ($DEBUG) {
-			print STDERR 'Lights: ' . $lights . "\n";
-		}
-
-		# Clear the override when the projector is off
-		if ($lights && !$projector) {
-			unlink($DATA_DIR . 'LIGHTS');
-		}
-	}
-
-	# Monitor the GUI, PLAYING, and MOTION files for changes only
-	{
-		my $mtime = mtime($DATA_DIR . 'PLAYING');
-		if ($mtime > $updateLast) {
-			$updateLast = $mtime;
-		}
-		$mtime = mtime($DATA_DIR . 'GUI');
-		if ($mtime > $updateLast) {
-			$updateLast = $mtime;
-		}
-		$mtime = mtime($DATA_DIR . 'MOTION');
-		if ($mtime > $updateLast) {
-			$updateLast = $mtime;
-		}
-	}
-
-	# Calculate the new state
-	$stateLast = $state;
-	if ($projector) {
-
-		# We are always either playing or paused if the projector is on
-		if ($playing) {
-
-			# Allow an override to higher brightness during playback
-			if ($lights) {
-				$state = 'PLAY_HIGH';
-			} else {
-				$state = 'PLAY';
-			}
-		} else {
-			$state = 'PAUSE';
-		}
-
-	} else {
-
-		# If the projector is off, check the timeouts
-		my $timeSinceUpdate = time() - $updateLast;
-		if ($timeSinceUpdate > $TIMEOUT) {
-			$state = 'OFF';
-		} elsif ($timeSinceUpdate < $TIMEOUT) {
-			$state = 'MOTION';
-		}
-	}
-	if ($state eq 'INIT') {
-		$state = 'OFF';
-	}
-
-	# Update the lighting state
-	if ($stateLast ne $state) {
-		if ($DEBUG) {
-			print STDERR 'State: ' . $stateLast . ' => ' . $state . "\n";
-			foreach my $data (@{ $DIM{$state} }) {
-				print STDERR "\t" . $data->{'channel'} . ' => ' . $data->{'value'} . ' @ ' . $data->{'time'} . "\n";
-			}
-		}
-
-		# Send the dim command
-		my @values = ();
-		foreach my $data (@{ $DIM{$state} }) {
-			dim($data->{'channel'}, $data->{'time'}, $data->{'value'});
-			push(@values, $data->{'channel'} . ' => ' . $data->{'value'} . ' @ ' . $data->{'time'});
-		}
-
-		# Save the state and value to disk
-		my ($fh, $tmp) = tempfile($DATA_DIR . 'ROPE.XXXXXXXX', 'UNLINK' => 0);
-		print $fh 'State: ' . $state . "\n" . join("\n", @values) . "\n";
-		close($fh);
-		rename($tmp, $DATA_DIR . 'ROPE');
-	}
-
-	# Wait and loop
-	usleep($DELAY);
-}
-
-sub mtime($) {
-	my ($file) = @_;
-	my $mtime = 0;
-	if (-r $file) {
-		(undef(), undef(), undef(), undef(), undef(), undef(), undef(), undef(), undef(), $mtime, undef(), undef(), undef()) = stat($file);
-	}
-	return $mtime;
-}
-
-# Send the command
-sub dim($$$) {
-	my ($channel, $duration, $intensity) = @_;
-	my $cmd = join(':', $channel, $duration, $intensity);
-	$sock->send($cmd)
-	  or die('Unable to write command to socket: ' . $CMD_FILE . ': ' . $cmd . ": ${!}\n");
-}

+ 0 - 88
dmx/setChannels.py

@@ -1,88 +0,0 @@
-#!/usr/bin/python
-import os
-import sys
-import array
-import string
-from ola.ClientWrapper import ClientWrapper
-
-wrapper = None
-dim = False
-dimTick = 0
-dimTime = 0
-numTicks = 0
-
-# Wrapper callback
-def DmxSent(state):
-  # Stop on errors
-  if not state.Succeeded():
-    wrapper.Stop()
-  
-  # Only run one command if we're setting
-  if not dim:
-    wrapper.Stop()
-  
-  # Stop when we're done dimming
-  if dim and dimTick >= numTicks:
-    wrapper.Stop()
-
-# Pick a universe (0, or as specified in the environment)
-universe = 0
-if 'UNIVERSE' in os.environ:
-  universe = int(os.environ['UNIVERSE'])
-
-# Pick a tick interval (50ms, or as specified in the environment)
-interval = 50
-if 'INTERVAL' in os.environ:
-  universe = int(os.environ['INTERVAL'])
-
-# Choose direct-set or dimming
-dim = False
-if 'dim' in string.lower(sys.argv[0]):
-  dim = True
-
-# If we are dimming, parse the command line into 3-part blocks
-# Otherwise just collect the intensities directly
-cmdData = [];
-if dim:
-  dimTime = int(sys.argv[1])
-  numTicks = dimTime / interval
-
-  for i in range(2, len(sys.argv), 2):
-      dimData = array.array('I')
-      dimData.append(int(sys.argv[i]))
-      dimData.append(int(sys.argv[i + 1]))
-      cmdData.append(dimData)
-else:
-  for i in range(1, len(sys.argv)):
-    cmdData.append(int(sys.argv[i]))
-
-def SendDMXFrame():
-  # Re-schedule ourselves in interval ms (do this first to keep the timing consistent)
-  if dim:
-    wrapper.AddEvent(interval, SendDMXFrame)
-  
-  # Eventually we need an array of intesnty bytes for each channel
-  data = array.array('B')
-
-  # Calculate intensities
-  if dim:
-    global dimTick
-    dimTick += 1
-    
-    for i in cmdData:
-      totalRange = i[1] - i[0]
-      delta = float(totalRange) / float(numTicks) * float(dimTick)
-      data.append(int(i[0] + delta))
-
-  else:
-    # Copy each intensity level from the command line
-    for i in cmdData:
-      data.append(i)
-  
-  # Send
-  wrapper.Client().SendDmx(universe, data, DmxSent)
-
-# Send the DMX command
-wrapper = ClientWrapper()
-wrapper.AddEvent(interval, SendDMXFrame)
-wrapper.Run()

+ 0 - 3
motion/.gitignore

@@ -1,3 +0,0 @@
-*.o
-MOTION
-USBMicroX

+ 0 - 829
motion/USBMicroX.c

@@ -1,829 +0,0 @@
-#include "USBMicroX.h"
-#define UNLESS(S) if(!(S))
-
-#define USBMX_ID_PRODUCT 0x01A5
-#define USBMX_ID_VENDOR 0x0DE7
-
-static long dict_get_long(CFDictionaryRef properties, CFStringRef key)
-{
-	long number;
-	CFTypeRef value = CFDictionaryGetValue(properties, key);
-	if (!value) return 0;
-	CFTypeID type = CFGetTypeID(value);
-	if (type != CFNumberGetTypeID()) return 0 ;
-	CFNumberGetValue((CFNumberRef)value, kCFNumberLongType, (void *)&number);
-	return number;
-}
-
-static char* dict_get_string(CFDictionaryRef properties, CFStringRef key, CFStringEncoding encoding)
-{
-	static char cstring[512];
-	CFTypeRef value = CFDictionaryGetValue(properties, key);
-	if (!value) return "";
-	CFTypeID type = CFGetTypeID(value) ;
-	if (type != CFStringGetTypeID()) return "";	
-	CFStringGetCString((CFStringRef)value, cstring, sizeof(cstring), encoding);
-	return cstring; // WARNING: be sure to copy string after return
-}
-
-static void nsp(int L) {
-	int i = 0;
-	while(i++ < L) printf("    ");
-}
-
-static void cftype_dump(CFTypeRef o, int L);
-
-static void cftype_dump_arrayapply(const void *value, void *context) {
-	int L = (int)context;
-	nsp(L); printf("0x%08x\n", value);
-	cftype_dump((CFTypeRef)value, L+1);
-}
-
-static void cftype_dump_dictapply (const void *key, const void *value, void *context) {
-	int L = (int)context;
-	nsp(L); printf("\"%s\" => 0x%08x\n",
-		CFStringGetCStringPtr(key, CFStringGetSystemEncoding()), value);
-	cftype_dump((CFTypeRef)value, L+1);
-}
-
-static void cftype_dump(CFTypeRef o, int L)
-{
-	if(CFGetTypeID(o) == CFArrayGetTypeID()) {
-		nsp(L); printf("[\n");
-		CFArrayApplyFunction(
-			o,
-			CFRangeMake(0, CFArrayGetCount(o)),
-			cftype_dump_arrayapply,
-			(void*)(L+1));
-		nsp(L); printf("]\n");
-	} else if(CFGetTypeID(o) == CFDictionaryGetTypeID()) {
-		nsp(L); printf("{\n");
-		CFDictionaryApplyFunction(
-			o,
-			cftype_dump_dictapply,
-			(void*)(L+1));
-		nsp(L); printf("}\n");
-	} else if(CFGetTypeID(o) == CFNumberGetTypeID()) {
-		long number;
-		CFNumberGetValue((CFNumberRef)o, kCFNumberLongType, (void*)&number);
-		nsp(L); printf("number: 0x%08x\n", number);
-	} else if(CFGetTypeID(o) == CFStringGetTypeID()) {
-		const char *s = CFStringGetCStringPtr(o, CFStringGetSystemEncoding());
-		nsp(L); printf("string: \"%s\"\n", s);
-	} else if(CFGetTypeID(o) == CFBooleanGetTypeID()) {
-		nsp(L); printf("boolean: %s\n", CFBooleanGetValue(o)?"TRUE":"FALSE");		
-	} else {
-		nsp(L); printf("??? unknown type\n");
-	}
-}
-
-int USBmX_DeviceAddedHandler(
-			USBmX_ContextRef ctx, 
-			USBmX_DeviceAddedProc proc, 
-			void *cookie)
-{
-	ctx->deviceAdded = proc;
-	ctx->deviceAdded_cookie = cookie;
-	return 0;
-}
-
-int USBmX_DeviceRemovedHandler(
-			USBmX_ContextRef ctx, 
-			USBmX_DeviceRemovedProc proc, 
-			void *cookie)
-{
-	ctx->deviceRemoved = proc;
-	ctx->deviceRemoved_cookie = cookie;
-	return 0;	
-}
-
-int USBmX_DeviceInfo(USBmX_DeviceRef dev)
-{
-	if(!dev) goto err;
-	cftype_dump(dev->properties, 0);
-	return 0;
-err:
-	return -1;
-}
-
-static void DumpBuffer(const u_char buf[], unsigned int buf_size)
-{
-	const u_char *p = buf;
-	while(buf_size--) printf("0x%02x ", *p++);
-	printf("\n");
-}
-
-void USBmX_DumpCommand(u_char buf[])
-{
-	DumpBuffer(buf, 8);
-}
-
-void DeviceAddedHandler(void *refCon, io_iterator_t iterator)
-{
-	#if USBMX_DEBUG_LOG
-	USBMX_LOG("Device added notification");
-	#endif
-	io_object_t o;
-	USBmX_ContextRef ctx;
-	// Must iterate in order to re-arm notification
-	while(o = IOIteratorNext(iterator)) {
-		IOObjectRelease(o);
-	}
-	ctx = (USBmX_ContextRef)refCon;
-	#if USBMX_DEBUG_LOG
-	USBMX_LOG("ctx = %x", ctx);
-	#endif
-	USBmX_ScanForDevices(ctx);
-}
-
-void DestroyDeviceRef(USBmX_DeviceRef d)
-{
-	#if USBMX_DEBUG_LOG
-	USBMX_LOG("Destroying: %x %x %x %x", d->properties, d->serialNumber, d->interface, d);
-	#endif
-	CFRelease(d->properties);
-	free((void *)d->serialNumber);
-	free((void *)d->deviceName);
-	free((void *)d->manufacturer);
-	(*d->interface)->close(d->interface);
-	free(d);
-}
-
-void DeviceRemovedHandler(void *target, IOReturn result, void *refcon, void *sender)
-{
-	USBmX_DeviceRef d = (USBmX_DeviceRef)refcon;
-	USBmX_ContextRef ctx = d->ctx;
-	#if USBMX_DEBUG_LOG
-	USBMX_LOG("Device Removed (# %s)", d->serialNumber);
-	#endif
-		
-	USBmX_DeviceRef p = ctx->deviceList;
-	USBmX_DeviceRef pl = NULL;
-	while(p) {
-		if(p == d)
-		{
-			if(pl == NULL)	ctx->deviceList = d->next;
-			else			pl->next = d->next;
-			////////////////////////////
-			//USBMX_LOG("NEED TO CALL DEVICE REMOVED CALLBACK");
-			if(ctx->deviceRemoved)
-			{
-				(*ctx->deviceRemoved)(d, ctx->deviceRemoved_cookie);
-			}
-			////////////////////////////
-			DestroyDeviceRef(d);
-			break;
-		}
-		pl = p;
-		p = p->next;
-	}
-}
-
-static void InterruptReportHandler(
-	void *target, 
-	IOReturn result, 
-	void *refcon, 
-	void *sender, 
-	UInt32 bufferSize)
-{
-	USBmX_DeviceRef d = (USBmX_DeviceRef)target;
-
-	#if USBMX_DEBUG_LOG
-	printf("Response: ");
-	DumpBuffer(d->response_buffer, bufferSize);
-	#endif
-	
-	d->response_ready = 1;
-}
-
-static int SetReport(USBmX_DeviceRef d, const u_char *buf, unsigned int buf_size)
-{
-	#if USBMX_DEBUG_LOG
-	printf("Report: "); DumpBuffer(buf, buf_size);
-	#endif
-	d->response_ready = 0;
-	IOReturn rc = (*d->interface)->setReport(
-		d->interface, 
-		kIOHIDReportTypeFeature,
-		0, //reportID
-		(void *)buf,
-		buf_size,
-		1000, //timeout
-		NULL,
-		NULL,
-		NULL
-		);
-	while(!d->response_ready) {
-		SInt32 r = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, false);
-		#if USBMX_DEBUG_LOG
-		printf("wait r=%x\n", r);
-		#endif
-	}
-	if(rc != kIOReturnSuccess) {
-		USBMX_LOG("SetReport: (*interface)->setReport() Error %x", rc);
-		return -1;
-	}
-	return 0;
-}
-
-int USBmX_DeviceCount(USBmX_ContextRef ctx)
-{
-	if(!ctx) return 0;
-	USBmX_DeviceRef d = ctx->deviceList;
-	int count = 0;
-	while(d) {
-		++count;
-		d = d->next;
-	}
-	return count;
-}
-
-USBmX_DeviceRef USBmX_DefaultDevice(USBmX_ContextRef ctx)
-{
-	if(ctx) return ctx->deviceList;
-	return NULL;
-}
-
-USBmX_DeviceRef USBmX_DeviceWithSerial(USBmX_ContextRef ctx, const char *serial)
-{
-	if(!ctx || !serial) return NULL;
-	USBmX_DeviceRef dev = ctx->deviceList;
-	#if USBMX_DEBUG_LOG
-	USBMX_LOG("Searching for device...");
-	#endif
-	while(dev) {
-		if(!strcmp(serial, dev->serialNumber))
-		{
-			#if USBMX_DEBUG_LOG
-			USBMX_LOG("Device found! %x (# %s)", dev, dev->serialNumber);
-			#endif			
-			return dev;
-		}
-		dev = dev->next;
-	}
-	#if USBMX_DEBUG_LOG
-	USBMX_LOG("Device not found");
-	#endif
-	return NULL;
-}
-
-int USBmX_RawCommand(USBmX_DeviceRef dev, 
-	const u_char command[8], 
-	u_char response[8])
-{
-	if(!dev) goto err;
-	if(SetReport(dev, command, 8) < 0) goto err;
-	if(response) {
-		memcpy(response, dev->response_buffer, 8);
-	}
-	return 0;
-err:
-	return -1;
-}
-
-static int CreateDeviceRef(USBmX_ContextRef ctx, io_object_t dev, USBmX_DeviceRef *dev_out)
-{
-	IOReturn rc;
-	kern_return_t result;
-
-	USBmX_DeviceRef dr = USBMX_ALLOC(USBmX_Device);
-	dr->next = NULL;
-	dr->ctx = ctx;
-	dr->userData = NULL;
-	
-	// Get device properties
-	result = IORegistryEntryCreateCFProperties(
-		dev, &dr->properties,
-		kCFAllocatorDefault, kNilOptions);
-	if(result != KERN_SUCCESS || !dr->properties) {
-		USBMX_LOG("IORegistryEntryCreateCFProperties Error %x", result);			
-		goto err;
-	}
-
-	dr->serialNumber = strdup(
-		dict_get_string(
-			dr->properties,
-			CFSTR(kIOHIDSerialNumberKey), 
-			CFStringGetSystemEncoding()));
-	dr->deviceName = strdup(
-		dict_get_string(
-			dr->properties,
-			CFSTR(kIOHIDProductKey), 
-			CFStringGetSystemEncoding()));
-	dr->manufacturer = strdup(
-		dict_get_string(
-			dr->properties,
-			CFSTR(kIOHIDManufacturerKey), 
-			CFStringGetSystemEncoding()));
-
-	// Add device to head of list if we don't already have it
-	if(USBmX_DeviceWithSerial(ctx, dr->serialNumber) == NULL)
-	{
-		#if USBMX_DEBUG_LOG
-		USBMX_LOG("Adding device");
-		#endif
-		dr->next = ctx->deviceList;
-		ctx->deviceList = dr;
-	} else {
-		#if USBMX_DEBUG_LOG
-		USBMX_LOG("Already have device");
-		#endif
-		return 0;
-	}
-
-	#if USBMX_DEBUG_LOG
-	USBMX_LOG("Found Device (# %s)", dr->serialNumber);
-	USBMX_LOG("kIOHIDManufacturerKey: \"%s\"",
-		dict_get_string(dr->properties, 
-		CFSTR(kIOHIDManufacturerKey), CFStringGetSystemEncoding()));
-	#endif
-
-	{	// Set up the device
-		SInt32 score = 0;
-		IOCFPlugInInterface **plugIn;
-
-		if((rc = IOCreatePlugInInterfaceForService(
-			dev,
-			kIOHIDDeviceUserClientTypeID,
-			kIOCFPlugInInterfaceID,
-			&plugIn, &score)) != kIOReturnSuccess)
-		{
-				USBMX_LOG("IOCreatePlugInInterfaceForService Error %x", rc);
-				goto err;
-		}
-		
-		// Grab interface
-		IOHIDDeviceInterface **interface;
-		HRESULT prc;
-		prc = (*plugIn)->QueryInterface(plugIn,
-			CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
-			(LPVOID)&interface);
-		(*plugIn)->Release(plugIn);
-		if(prc != S_OK) {
-			USBMX_LOG("QueryInterface Error %x", prc);
-			goto err;
-		}
-		
-		dr->interface = interface;
-
-		// Set up removal callback
-		if((rc = (*interface)->setRemovalCallback(interface, 
-			DeviceRemovedHandler, NULL, (void *)dr)) != kIOReturnSuccess)
-		{
-			USBMX_LOG("(*interface)->setRemovalCallback() Error %x", rc);
-			goto err1;
-		}
-
-		if((rc = (*interface)->open(interface, 0)) != kIOReturnSuccess)
-		{
-			USBMX_LOG("(*interface)->open() Error %x", rc);
-			goto err1;
-        }
-
-		mach_port_t async_port;
-		if((rc = (*interface)->createAsyncPort(interface, &async_port)) != kIOReturnSuccess)
-		{
-			USBMX_LOG("(*interface)->createAsyncPort() Error %x", rc);
-			goto err1;
-        }
-		
-		CFRunLoopSourceRef rl_source;
-		if((rc = (*interface)->createAsyncEventSource(interface, &rl_source)) != kIOReturnSuccess)
-		{
-			USBMX_LOG("(*interface)->createAsyncEventSource() Error %x", rc);
-			goto err1;
-		}
-
-		CFRunLoopAddSource(
-			CFRunLoopGetCurrent(),
-			rl_source,
-			kCFRunLoopDefaultMode);
-		if((rc = ((IOHIDDeviceInterface122*)*interface)->setInterruptReportHandlerCallback(
-			interface,
-			dr->response_buffer,
-			USBMX_RESPONSE_BUFFER_SIZE,
-			InterruptReportHandler,
-			(void *)dr,
-			NULL)) != kIOReturnSuccess)
-		{
-			USBMX_LOG("(*interface)->setInterruptReportHandlerCallback() Error %x", rc);
-			goto err1;
-		}
-	}
-	
-	*dev_out = dr;
-	////////////////
-	//USBMX_LOG("NEED TO CALL DEVICE ADDED CALLBACK");
-	if(ctx->deviceAdded)
-	{
-		(*ctx->deviceAdded)(dr, ctx->deviceAdded_cookie);
-	}
-	////////////////
-	return 0;
-err1:
-	(*dr->interface)->Release(dr->interface);
-err:
-	IOObjectRelease(dev);
-	free(dr);
-	return -1;
-}
-
-int USBmX_ScanForDevices(USBmX_ContextRef ctx)
-{
-	IOReturn rc;	
-	io_iterator_t iterator;
-	io_object_t d;
-	int n_devices = 0;
-	
-	CFRetain(ctx->matchingDict);
-	
-	// Narrow it down to devices matching vendor and product IDs
-	if(rc = IOServiceGetMatchingServices(
-		kIOMasterPortDefault,
-		ctx->matchingDict,
-		&iterator) != kIOReturnSuccess)
-	{
-			USBMX_LOG("IOServiceGetMatchingServices Error %x", rc);
-			goto err;
-	}
-
-	// Iterate over each found device
-	while(d = IOIteratorNext(iterator))
-	{
-		USBmX_DeviceRef dev;
-		if(CreateDeviceRef(ctx, d, &dev) < 0) goto err1;
-		n_devices++;
-	}
-	
-	IOObjectRelease(iterator);
-
-noerr:
-	return n_devices;
-err1:
-	IOObjectRelease(iterator);
-err:
-	USBMX_LOG("USBmX_FindDevices Failed!");
-	return -1;
-}
-
-USBmX_ContextRef USBmX_Create(void)
-{
-	USBmX_ContextRef ctx = NULL;
-	if(ctx = USBMX_ALLOC(USBmX_Context))
-	{
-		ctx->deviceList = NULL;
-		ctx->matchingDict = NULL;
-		ctx->deviceAdded = NULL;
-		ctx->deviceRemoved = NULL;
-		ctx->deviceAdded_cookie = NULL;
-		ctx->deviceRemoved_cookie = NULL;
-	}
-	return ctx;
-}
-
-int USBmX_Begin(USBmX_ContextRef ctx)
-{
-//	USBmX_ContextRef ctx = USBMX_ALLOC(USBmX_Context);
-//	ctx->deviceList = NULL;
-//	ctx->matchingDict = NULL;
-	if(!ctx) return -1;
-
-	// Grab root IOKit HID services
-	UNLESS(ctx->matchingDict = IOServiceMatching(kIOHIDDeviceKey))
-	{
-		USBMX_LOG("IOServiceMatching(kIOHIDDeviceKey) Error");
-		goto err;
-	}
-
-	{	// Add product and vendor keys to matchingDict
-		SInt32 product = USBMX_ID_PRODUCT;
-		SInt32 vendor = USBMX_ID_VENDOR;
-		CFNumberRef num = NULL;
-		#define USBMX_DNA(NAME, VALUE) \
-			UNLESS(num = CFNumberCreate( \
-					kCFAllocatorDefault, \
-					kCFNumberSInt32Type, \
-					& VALUE )) { \
-				USBMX_LOG("CFNumber Error"); \
-				goto err; \
-			} \
-			CFDictionaryAddValue(ctx->matchingDict, CFSTR(NAME), num); \
-			CFRelease(num);
-		USBMX_DNA(kIOHIDVendorIDKey, vendor)
-		USBMX_DNA(kIOHIDProductIDKey, product)
-		#undef USBMX_DNA
-	}
-
-	{	// Set up onPlug handler
-		io_iterator_t plugIterator;
-		IONotificationPortRef plugPort;
-		//CFRunLoopSourceRef runLoopSource;
-		
-		//CFMutableDictionaryRef hd = IOServiceMatching(kIOHIDDeviceKey);
-		CFRetain(ctx->matchingDict);
-
-		UNLESS(plugPort = IONotificationPortCreate(kIOMasterPortDefault))
-		{
-			USBMX_LOG("IONotificationPortCreate error");		
-		}
-		
-		CFRunLoopAddSource(
-			CFRunLoopGetCurrent(),
-			IONotificationPortGetRunLoopSource(plugPort),
-			kCFRunLoopDefaultMode);
-		if(IOServiceAddMatchingNotification(
-			plugPort,
-			kIOFirstMatchNotification,
-			ctx->matchingDict,
-			DeviceAddedHandler,
-			(void *)ctx,
-			&plugIterator) != KERN_SUCCESS)
-		{
-			USBMX_LOG("IOServiceAddMatchingNotification error");		
-		}
-		DeviceAddedHandler((void *)ctx, plugIterator);
-	}
-
-	//if(USBmX_ScanForDevices(ctx) < 0) goto err;
-noerr:
-	//return ctx;
-	return 0;
-err:
-	USBMX_LOG("USBmX_Init Failed!");
-	free(ctx);
-	//return NULL;
-	return -1;
-}
-
-int USBmX_Destroy(USBmX_ContextRef ctx)
-{
-	if(!ctx) return -1;
-	free(ctx);
-	return 0;
-}
-
-int USBmX_InitPorts(USBmX_DeviceRef dev)
-{
-	int r;
-	u_char res[8];
-	static const u_char cmd[8] = {
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00
-	};
-	r = USBmX_RawCommand(dev, cmd, res);
-	if(r < 0) return r;
-	if(res[0] != cmd[0]) return -1;
-	return 0;
-}
-
-int USBmX_WriteA(USBmX_DeviceRef dev, u_char value)
-{
-	int r;
-	u_char res[8];
-	u_char cmd[8] = {
-		0x01,
-		value,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00
-	};
-	r = USBmX_RawCommand(dev, cmd, res);
-	if(r < 0) return r;
-	if(res[0] != cmd[0]) return -1;
-	return 0;	
-}
-
-int USBmX_WriteB(USBmX_DeviceRef dev, u_char value)
-{
-	int r;
-	u_char res[8];
-	u_char cmd[8] = {
-		0x02,
-		value,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00
-	};
-	r = USBmX_RawCommand(dev, cmd, res);
-	if(r < 0) return r;
-	if(res[0] != cmd[0]) return -1;
-	return 0;	
-}
-
-int USBmX_WriteABit(USBmX_DeviceRef dev, u_char v_and, u_char v_or)
-{
-	int r;
-	u_char res[8];
-	u_char cmd[8] = {
-		0x03,
-		v_and,
-		v_or,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00
-	};
-	r = USBmX_RawCommand(dev, cmd, res);
-	if(r < 0) return r;
-	if(res[0] != cmd[0]) return -1;
-	return 0;	
-}
-
-int USBmX_WriteBBit(USBmX_DeviceRef dev, u_char v_and, u_char v_or)
-{
-	int r;
-	u_char res[8];
-	u_char cmd[8] = {
-		0x04,
-		v_and,
-		v_or,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00
-	};
-	r = USBmX_RawCommand(dev, cmd, res);
-	if(r < 0) return r;
-	if(res[0] != cmd[0]) return -1;
-	return 0;	
-}
-
-int USBmX_ReadA(USBmX_DeviceRef dev, u_char *value_out)
-{
-	int r;
-	u_char res[8];
-	u_char cmd[8] = {
-		0x05,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00
-	};
-	r = USBmX_RawCommand(dev, cmd, res);
-	if(value_out) *value_out = res[1];
-	if(r < 0) return r;
-	if(res[0] != cmd[0]) return -1;
-	return 0;
-}
-
-int USBmX_ReadB(USBmX_DeviceRef dev, u_char *value_out)
-{
-	int r;
-	u_char res[8];
-	u_char cmd[8] = {
-		0x06,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00
-	};
-	r = USBmX_RawCommand(dev, cmd, res);
-	if(value_out) *value_out = res[1];
-	if(r < 0) return r;
-	if(res[0] != cmd[0]) return -1;
-	return 0;
-}
-
-int USBmX_SetBit(USBmX_DeviceRef dev, u_char line)
-{
-	int r;
-	u_char res[8];
-	u_char cmd[8] = {
-		0x07,
-		line,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00
-	};
-	r = USBmX_RawCommand(dev, cmd, res);
-	if(r < 0) return r;
-	if(res[0] != cmd[0]) return -1;
-	return 0;
-}
-
-int USBmX_ResetBit(USBmX_DeviceRef dev, u_char line)
-{
-	int r;
-	u_char res[8];
-	u_char cmd[8] = {
-		0x08,
-		line,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00
-	};
-	r = USBmX_RawCommand(dev, cmd, res);
-	if(r < 0) return r;
-	if(res[0] != cmd[0]) return -1;
-	return 0;
-}
-
-int USBmX_DirectionA(USBmX_DeviceRef dev, u_char dir0, u_char dir1)
-{
-	int r;
-	u_char res[8];
-	u_char cmd[8] = {
-		0x09,
-		dir0,
-		dir1,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00
-	};
-	r = USBmX_RawCommand(dev, cmd, res);
-	if(r < 0) return r;
-	if(res[0] != cmd[0]) return -1;
-	return 0;
-}
-
-int USBmX_DirectionB(USBmX_DeviceRef dev, u_char dir0, u_char dir1)
-{
-	int r;
-	u_char res[8];
-	u_char cmd[8] = {
-		0x0A,
-		dir0,
-		dir1,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x00
-	};
-	r = USBmX_RawCommand(dev, cmd, res);
-	if(r < 0) return r;
-	if(res[0] != cmd[0]) return -1;
-	return 0;
-}
-
-int USBmX_StrobeWrite(USBmX_DeviceRef dev, 
-	u_char data, 
-	u_char port_select, 
-	u_char strobe_line,
-	u_char pulse_length)
-{
-	return -1;
-}
-
-int USBmX_StrobeRead(USBmX_DeviceRef dev, 
-	u_char *data_out, 
-	u_char port_select, 
-	u_char strobe_line,
-	u_char pulse_length)
-{
-	return -1;
-}
-
-int USBmX_StrobeWrites(USBmX_DeviceRef dev, 
-	u_char n_bytes, 
-	u_char bytes[])
-{
-	return -1;
-}
-
-int USBmX_InitLCD(USBmX_DeviceRef dev,
-	u_char rw_select,
-	u_char rs_select,
-	u_char port_select,
-	u_char e_select)
-{
-	return -1;
-}
-
-int USBmX_LCDCmd(USBmX_DeviceRef dev, u_char cmd)
-{
-	return -1;
-}
-
-int USBmX_LCDData(USBmX_DeviceRef dev, u_char data)
-{
-	return -1;
-}

+ 0 - 350
motion/USBMicroX.h

@@ -1,350 +0,0 @@
-#ifndef _USBMICROX_H_
-#define _USBMICROX_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <libgen.h>
-#include <mach/mach.h>
-#include <sys/types.h>
-#include <CoreFoundation/CFNumber.h>
-#include <CoreFoundation/CoreFoundation.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOCFPlugIn.h>
-#include <IOKit/usb/IOUSBLib.h>
-#include <IOKit/hid/IOHIDLib.h>
-#include <IOKit/hid/IOHIDKeys.h>
-
-#define USBMX_LOG(S, ...) \
-	({ fprintf(stderr, "/%s/%s/%d >>> " S "\n", basename(__FILE__) , \
-	__FUNCTION__ , __LINE__ , ## __VA_ARGS__ ); })
-#define USBMX_CMD(...) (u_char[8]){ __VA_ARGS__ }
-#define USBMX_ALLOC(TYPE) (TYPE*)malloc(sizeof(TYPE))
-
-#define USBMX_DEBUG_LOG 0
-#define USBMX_RESPONSE_BUFFER_SIZE 8
-
-struct _USBmX_Context;
-
-typedef struct _USBmX_Device {
-	struct _USBmX_Context *ctx;
-	IOHIDDeviceInterface **interface;
-	CFMutableDictionaryRef properties;
-	const char *serialNumber;
-	const char *deviceName;
-	const char *manufacturer;
-	int response_ready;
-	u_char response_buffer[USBMX_RESPONSE_BUFFER_SIZE];
-	struct _USBmX_Device *next;
-	void *userData;
-} USBmX_Device;
-typedef USBmX_Device* USBmX_DeviceRef;
-
-typedef void (*USBmX_DeviceAddedProc)(USBmX_DeviceRef dev, void *cookie);
-typedef void (*USBmX_DeviceRemovedProc)(USBmX_DeviceRef dev, void *cookie);
-
-typedef struct _USBmX_Context {
-	USBmX_DeviceRef deviceList;
-	CFMutableDictionaryRef matchingDict;
-	USBmX_DeviceAddedProc deviceAdded;
-	USBmX_DeviceRemovedProc deviceRemoved;
-	void *deviceAdded_cookie;
-	void *deviceRemoved_cookie;
-} USBmX_Context;
-typedef USBmX_Context* USBmX_ContextRef;
-
-/*
- *	USBmX_Create:
- *	Creates a USBmX_ContextRef used in all other
- *	routines.  Should return a valid USBmX_ContextRef
- *	even if no devices are conected.
- */
-extern USBmX_ContextRef USBmX_Create(void);
-
-extern int USBmX_DeviceAddedHandler(
-			USBmX_ContextRef ctx, 
-			USBmX_DeviceAddedProc proc, 
-			void *cookie);
-extern int USBmX_DeviceRemovedHandler(
-			USBmX_ContextRef ctx, 
-			USBmX_DeviceRemovedProc proc, 
-			void *cookie);
-
-/*
- *	USBmX_Begin:
- *	You must call USBmX_Begin to init the USB
- *	subsystem.  Call before sending any commands.
- *	Returns < 0 on error.
- */
-extern int USBmX_Begin(USBmX_ContextRef ctx);
-
-/*
- *	USBmX_ScanForDevices:
- *	Call to manually re-scan the USB bus for newly
- *	connected devices.  You should never have to
- *	call this yourself (there are internal
- *	notifications that should call this automatically
- *	when a device is plugged in.
- *	Returns < 0 on error.
- */
-extern int USBmX_ScanForDevices(USBmX_ContextRef ctx);
-
-/*
- *	USBmX_Destroy:
- *	Call when you are done messing with all devices.
- */
-extern int USBmX_Destroy(USBmX_ContextRef ctx);
-
-/*
- *	USBmX_DeviceCount:
- *	Get the number of connected devices.
- */
-extern int USBmX_DeviceCount(USBmX_ContextRef ctx);
-
-/*
- *	USBmX_DefaultDevice:
- *	Get the default devico (generally the last device
- *	that was plugged in.  Useful if you only have 1
- *	device plugged in and don't want to mess with the
- *	serial number.  Returns NULL if there are no
- *	devices connected.
- */
-extern USBmX_DeviceRef USBmX_DefaultDevice(USBmX_ContextRef ctx);
-
-/*
- *	USBmX_DeviceWithSerial:
- *	Get the device matching the provided serial
- *	number.  Returns NULL if the device cannot be
- *	found.
- */
-extern USBmX_DeviceRef USBmX_DeviceWithSerial(USBmX_ContextRef ctx, const char *serial);
-
-/*
- *	USBmX_DumpCommand:
- *	Small utility function that prints out an 8 byte
- *	buffer in human readable form.  Useful for
- *	printing commands and responses.
- */
-extern void USBmX_DumpCommand(u_char buf[]);
-
-/*
- *	USBmX_DeviceInfo:
- *	Outputs as much infomation as possible on a
- *	given device.
- */
-extern int USBmX_DeviceInfo(USBmX_DeviceRef dev);
-
-
-/*
-*****************************************************
-*****************  Commands  ************************
-*****************************************************
-The following command functions return 0 on success
-and < 0 on error.
-
-Where the command demands that you chose a 'line'
-(A0..A7, or B0..B7), the table below may be helpful:
-Value	Line
------	----
-0x00	A0
-0x01	A1
-0x02	A2
-0x03	A3
-0x04	A4
-0x05	A5
-0x06	A6
-0x07	A7
-0x08	B0
-0x09	B1
-0x0A	B2
-0x0B	B3
-0x0C	B4
-0x0D	B5
-0x0E	B6
-0x0F	B7
-*/
-
-
-/*
- *	USBmX_RawCommand:
- *	Performs a raw command on the specifie device.
- *	More info can be found here:
- *	http://usbmicro.com/odn/index.html
- *	under "Raw Command Summary"
- */
-extern int USBmX_RawCommand(USBmX_DeviceRef dev, 
-	const u_char command[8], 
-	u_char response[8]);
-
-/*
-The initial state of the ports on power up is that all
-of the 16 lines are set to be inputs. This command 
-duplicates the power up conditions of setting all lines 
-to input.
-*/
-extern int USBmX_InitPorts(USBmX_DeviceRef dev);
-
-/*
-Write a byte value to specified port. The possible values 
-range from 0-255 (0x00..0xFF) (passed in value).
-*/
-extern int USBmX_WriteA(USBmX_DeviceRef dev, u_char value);
-extern int USBmX_WriteB(USBmX_DeviceRef dev, u_char value);
-
-/*
-Write masked values to specified port. The net result of 
-writing masked values is that only the specified bits will 
-be written. The resulting port condition is the logic 
-combination of the current port state ANDed with the 
-first term (v_and) and then ORed with the second (v_or). 
-This command can affect any number of lines on the port.
-*/
-extern int USBmX_WriteABit(USBmX_DeviceRef dev, u_char v_and, u_char v_or);
-extern int USBmX_WriteBBit(USBmX_DeviceRef dev, u_char v_and, u_char v_or);
-
-/*
-Read a byte value from specified port. The returned value
-(returned in *value_out) is the state of the port lines that 
-an external device has set, if the line is an input. 
-The lines that might be configured as outputs return the 
-output state.
-*/
-extern int USBmX_ReadA(USBmX_DeviceRef dev, u_char *value_out);
-extern int USBmX_ReadB(USBmX_DeviceRef dev, u_char *value_out);
-
-/*
-Set a single bit/line high. (0..15)
-*/
-extern int USBmX_SetBit(USBmX_DeviceRef dev, u_char line);
-
-/*
-Set a single bit/line low. (0..15)
-*/
-extern int USBmX_ResetBit(USBmX_DeviceRef dev, u_char line);
-
-/*
-Set the i/o direction of specified port.
-dir0 is written to the direction0 control register, dir1 
-is written to the direction1 control register appropriate 
-for the port.
-The individual pins of the ports can be set to input, or 
-output. Input is set when both bits associated with a 
-particular line are set to 0. There are different types 
-of outputs available for the board, but generally setting 
-both of the direction bits to 1 will suffice.
-High order bits of dir0 and dir1 correspond to high order
-lines.
-*/
-extern int USBmX_DirectionA(USBmX_DeviceRef dev, u_char dir0, u_char dir1);
-extern int USBmX_DirectionB(USBmX_DeviceRef dev, u_char dir0, u_char dir1);
-
-/*
-Strobe write of a byte value to a port. This command 
-selects port A (port_select=0x00) or B (port_select=0x01) 
-for the written byte, as well as a polarity (negative or 
-positive) and a line (A.0 - B.7 (strobe_line=0..15)) to 
-toggle. The byte is written and then the line toggled.
-pulse_length can be anywhere between 0x00..0xFF.
-Default is to have the strobe negative-going 
-(high->low->high).  Add 0x10 to strobe_line to have the
-pulse be positive-going (low->high->low).
-*/
-extern int USBmX_StrobeWrite(USBmX_DeviceRef dev, 
-	u_char data, 
-	u_char port_select, 
-	u_char strobe_line,
-	u_char pulse_length);
-
-/*
-Strobe read of a byte value from a port. This command 
-selects port A (port_select=0x00) or B (port_select=0x01) 
-for the read byte, as well as a polarity (negative or 
-positive) and a line (A.0 - B.7 (strobe_line=0..15)) to 
-toggle. The line is toggled and the byte is read.
-pulse_length can be anywhere between 0x00..0xFF.
-Default is to have the strobe negative-going 
-(high->low->high).  Add 0x10 to strobe_line to have the
-pulse be positive-going (low->high->low).
-*data_out is set to the byte read.
-*/
-extern int USBmX_StrobeRead(USBmX_DeviceRef dev, 
-	u_char *data_out, 
-	u_char port_select, 
-	u_char strobe_line,
-	u_char pulse_length);
-
-/*
-Strobe write of a 1 to 6 byte value to a port. This 
-command uses port A or B for the written byte, as well 
-as a polarity (negative or positive) and a line 
-(A.0 - B.7) to toggle based on the previously executed 
-USBmX_StrobeWrite or USBmX_StrobeRead.
-Control this command's port for the written byte, 
-polarity and strobe line by using the USBmX_StrobeWrite 
-or USBmX_StrobeRead. This command will then use the 
-same selected port, polarity, and strobe line to write 
-up to 6 bytes.
-n_bytes is the number of bytes to write.
-bytes[] is an array of bytes, the first n_bytes values
-will be written.  It must be at least of size n_bytes.
-*/
-extern int USBmX_StrobeWrites(USBmX_DeviceRef dev, 
-	u_char n_bytes, 
-	u_char bytes[]);
-
-/*
-Strobe read of a 1 to 6 byte value from a port. This 
-command uses port A or B for the read byte, as well 
-as a polarity (negative or positive) and a line 
-(A.0 - B.7) to toggle based on the previously executed 
-USBmX_StrobeWrite or USBmX_StrobeRead.
-Control this command's port for the written byte, 
-polarity and strobe line by using the USBmX_StrobeWrite 
-or USBmX_StrobeRead. This command will then use the 
-same selected port, polarity, and strobe line to read 
-up to 6 bytes.
-n_bytes is the number of bytes to read.
-bytes[] is an array of bytes that the read values will be 
-copied into.  It must be at least of size n_bytes.
-*/
-extern int USBmX_StrobeReads(USBmX_DeviceRef dev, 
-	u_char n_bytes, 
-	u_char bytes[]);
-
-/*
-Initialize LCD variables. This includes the selection 
-of the lines used for RW, RS, E and the port used for 
-data. RW, RS, and E are reset. These commands are 
-appropriate for HD44780 devices and devices that are 
-compatible.
-port_select = 0 for port A, or 1 for port B.
-See table (way) above for line->number mappings.
-*/
-extern int USBmX_InitLCD(USBmX_DeviceRef dev,
-	u_char rw_select,
-	u_char rs_select,
-	u_char port_select,
-	u_char e_select);
-	
-/*
-Write a command to the LCD. The RS, RW, E lines and the 
-data port are selected by the USBmX_InitLCD. The data 
-byte is written to the selected port and the control 
-lines are set appropriately. The E line is toggled for 
-five to eight microseconds.
-*/
-extern int USBmX_LCDCmd(USBmX_DeviceRef dev, u_char cmd);
-
-/*
-Write a character to the LCD. The RS, RW, E lines and 
-the data port are selected by the USBmX_InitLCD. The data 
-byte is written to the selected port and the control 
-lines are set appropriately. The E line is toggled for 
-five to eight microseconds.
-*/
-extern int USBmX_LCDData(USBmX_DeviceRef dev, u_char data);
-
-// TODO: SPI + Stepper
-
-#endif /* _USBMICROX_H_ */

+ 0 - 25
motion/launchd/com.uberzach.motion.plist

@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>UserName</key>
-	<string>tv</string>
-	<key>LimitLoadToHosts</key>
-	<array>
-		<string>heady.uberzach.com</string>
-	</array>
-	<key>RunAtLoad</key>
-	<true/>
-	<key>Label</key>
-	<string>com.uberzach.motion</string>
-	<key>KeepAlive</key>
-	<dict>
-		<key>NetworkState</key>
-		<true/>
-	</dict>
-	<key>ProgramArguments</key>
-	<array>
-		<string>/Users/tv/bin/video/motion/USBMicroX</string>
-	</array>
-</dict>
-</plist>

+ 0 - 173
motion/main.c

@@ -1,173 +0,0 @@
-#include "USBMicroX.h"
-#include <fcntl.h>
-#include <sys/stat.h>
-
-#define DATA_DIR "plexMonitor/"
-#define OUT_FILE "MOTION"
-#define NUM_DEVICES 2
-#define SERIALS { "101128160542", "101128155210" }
-#define SLEEP_DELAY 250000
-#define TIMEOUT 2
-
-//#define DEBUG
-
-// Typedef
-typedef unsigned char u8;
-
-// Prototypes
-void timeout(int sig);
-USBmX_DeviceRef init();
-u8 readDev(USBmX_DeviceRef dev);
-char * initPaths();
-
-// Globals
-USBmX_ContextRef ctx;
-
-int main(int argc, const char * argv[])
-{
-	char *outfile;
-	unsigned int i, motion;
-	USBmX_DeviceRef device[NUM_DEVICES];
-	const char *serials[NUM_DEVICES] = SERIALS;
-
-	// Setup the output file
-	outfile = initPaths();
-
-	// Monitor for alarms
-	signal(SIGALRM, timeout);
-
-	// Setup the USB devices
-	for (i = 0; i < NUM_DEVICES; i++) {
-		device[i] = init(serials[i]);
-	}
-	
-	// Read forever
-	while (1) {
-		// Check for motion in any device
-		motion = 0;
-		for (i = 0; i < NUM_DEVICES; i++) {
-			if (readDev(device[i])) {
-				motion = 1;
-				i = NUM_DEVICES;
-			}
-		}
-
-		// If we detected motion
-		if (motion > 0) {
-			#ifdef DEBUG
-			printf("Motion detected\n");
-			#endif
-			if (utimes(outfile, NULL) != 0) {
-				if (errno == ENOENT) {
-				} else {
-					fprintf(stderr, "Error touching output file (%s): %s\n", strerror(errno), outfile);
-				}
-			}
-		} else {
-			#ifdef DEBUG
-			printf("\n");
-			#endif
-		}	
-
-		// Delay and loop
-		usleep(SLEEP_DELAY);
-	}
-	
-	// Cleanup (we never get here)
-	USBmX_Destroy(ctx);
-	return 0;
-}
-
-// Catch the timeout
-void timeout(int sig) {
-	signal(sig, SIG_IGN);
-	fprintf(stderr, "Timeout waiting for USB read\n");
-	exit(1);
-}
-
-// Setup the USBMicro context and build refs to our specified devices
-USBmX_DeviceRef init(const char *serial) {
-	USBmX_DeviceRef device;
-
-	// Create a new USBmicroX context as needed
-	if (!ctx) {
-		ctx = USBmX_Create();
-		USBmX_Begin(ctx);
-	}
-
-	// Find the specified device
-	device = USBmX_DeviceWithSerial(ctx, serial);
-	if (!device) {
-		fprintf(stderr, "Device not found: %s\n", serial);
-		exit(1);
-	}
-
-	// Return device handle
-	return device;
-}
-
-// Read the specified USBMicro device
-u8 readDev(USBmX_DeviceRef dev) {
-	unsigned char data = 0x00;
-
-	// Enable the timeout
-	alarm(TIMEOUT);
-
-	// Read from the device
-	if (USBmX_ReadA(dev, &data) != 0) {
-		fprintf(stderr, "Device read error\n");
-		exit(1);
-	}
-
-	// Clear the timeout
-	alarm(0);
-
-	// Return pin A5
-	return (data & 0x20);
-}
-
-// Setup the data directory and output file
-char * initPaths() {
-	int fd;
-	size_t len;
-	char *datadir, *outfile;
-	struct stat statbuf;
-
-	// Construct the data directory and output file paths
-	len = confstr(_CS_DARWIN_USER_TEMP_DIR, NULL, (size_t) 0);
-	len += sizeof(DATA_DIR);
-	datadir = malloc(len);
-	outfile = malloc(len + sizeof(OUT_FILE));
-	if (datadir == NULL || outfile == NULL) {
-		fprintf(stderr, "Out of memory\n");
-		exit(1);
-	}
-	confstr(_CS_DARWIN_USER_TEMP_DIR, datadir, len);
-	strlcat(datadir, DATA_DIR, len);
-	strlcpy(outfile, datadir, len);
-	strlcat(outfile, OUT_FILE, len + sizeof(OUT_FILE));
-
-	// Create the datadir as needed
-	stat(datadir, &statbuf);
-	if (!S_ISDIR(statbuf.st_mode)) {
-		fprintf(stderr, "Creating data directory: %s\n", datadir);
-		if (mkdir(datadir, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
-			fprintf(stderr, "Error creating data directory (%s): %s\n", strerror(errno), outfile);
-			exit(1);
-		}
-	}
-
-	// Create the output file as needed
-	stat(outfile, &statbuf);
-	if(!S_ISREG(statbuf.st_mode)) {
-		fprintf(stderr, "Creating output file: %s\n", outfile);
-		fd = open(outfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-		if (fd <= 0 || close(fd) != 0) {
-			fprintf(stderr, "Error creating output file (%s): %s\n", strerror(errno), outfile);
-			exit(1);
-		}
-	}
-
-	// Return the output file path
-	return outfile;
-}

+ 0 - 13
motion/makefile

@@ -1,13 +0,0 @@
-default: USBMicroX
-
-USBMicroX: USBMicroX.o main.o
-	gcc -framework CoreFoundation -framework IOKit -o USBMicroX USBMicroX.o main.o
-
-main.o: main.c
-	gcc -c main.c
-
-USBMicroX.o: USBMicroX.c USBMicroX.h
-	gcc -c USBMicroX.c
-
-clean:
-	rm -f main.o USBMicroX.o USBMicroX

+ 0 - 56
plex

@@ -1,56 +0,0 @@
-#!/bin/bash
-
-# Parameters
-USER="plex"
-PASS="bobola22"
-HOST="localhost"
-PORT="3000"
-
-# Figure out what we should do
-CMD="`basename "${0}" | sed 's%^plex\-%%' | tr a-z A-Z`"
-
-# Reduce typing
-CURL="curl --silent --get --user ${USER}:${PASS}"
-RPATH="/xbmcCmds/xbmcHttp"
-URL="http://${HOST}:${PORT}${RPATH}"
-OUTPUT=0
-
-# Pick a command
-if [ "${CMD}" == "UPDATE" ]; then
-	URL="${URL}/?command=ExecBuiltIn&parameter=XBMC.updatelibrary(video)"
-elif [ "${CMD}" == "CLEAN" ]; then
-	URL="${URL}?command=ExecBuiltIn&parameter=XBMC.CleanLibrary(video)"
-elif [ "${CMD}" == "FILES" ]; then
-	URL="${URL}?command=queryvideodatabase(SELECT%20path.strPath,%20files.strFilename%20FROM%20path%20JOIN%20files%20ON%20path.idPath%20=%20files.idPath%20JOIN%20episode%20ON%20files.idFile%20=%20episode.idFile)"
-	OUTPUT=1
-elif [ "${CMD}" == "BUTTON" ]; then
-	URL="${URL}?command=SendKey(${1})"
-elif [ "${CMD}" == "PLAYING" ]; then
-	URL="${URL}?command=GetCurrentlyPlaying"
-	OUTPUT=1
-elif [ "${CMD}" == "RESOLUTION" ]; then
-	URL="${URL}?command=GetGuiDescription"
-	OUTPUT=1
-elif [ "${CMD}" == "GUI" ]; then
-	URL="${URL}?command=GetGuiStatus"
-	OUTPUT=1
-else
-	echo "Unknown command: ${CMD}" 1>&2
-	exit 1
-fi
-
-# Bail if Plex is not running
-if ! ps awx -o comm= | grep -v 'Media Server' | grep -q 'MacOS/Plex'; then
-	if [ $OUTPUT -gt 0 ]; then
-		echo "Plex is not running" 1>&2
-		exit 1
-	fi
-	exit 0
-fi
-
-# Run the command
-if [ $OUTPUT -gt 0 ]; then
-	$CURL "${URL}"
-else
-	$CURL "${URL}" >/dev/null
-fi

+ 0 - 1
plex-button

@@ -1 +0,0 @@
-plex

+ 0 - 23
plex-checkTV

@@ -1,23 +0,0 @@
-#!/bin/bash
-
-# Path must be the default /Volumes and not /mnt -- Plex stores the former in its DB
-TV_PATH="/Volumes/media/TV"
-
-# Get the list of TV files in the library
-LIB_TEMP="`mktemp -t 'checkTV.XXXXXXXX'`"
-~/bin/video/plex-files | ~/bin/video/plex-filter | grep "^${TV_PATH}/" | sort -f > "${LIB_TEMP}"
-
-# Bail if we did not find anything
-if [ `cat "${LIB_TEMP}" | wc -l` -lt 1 ]; then
-	exit 1
-fi
-
-# Get the list of all files on the disk
-DISK_TEMP="`mktemp -t 'checkTV.XXXXXXXX'`"
-find "${TV_PATH}" -type f -name '*.m[op4k][4v]' | grep -v '\/\._' | sort -f > "${DISK_TEMP}"
-
-# Compare
-diff -i -U 0 "${DISK_TEMP}" "${LIB_TEMP}" | grep -v '^---' | grep -v '^+++' | grep -v '@@' | grep -v '^+'
-
-# Cleanup
-rm -rf "${LIB_TEMP}" "${DISK_TEMP}"

+ 0 - 1
plex-clean

@@ -1 +0,0 @@
-plex

+ 0 - 1
plex-files

@@ -1 +0,0 @@
-plex

+ 0 - 18
plex-filter

@@ -1,18 +0,0 @@
-#!/usr/bin/perl -w
-use strict;
-
-my $prefix = '';
-while (<STDIN>) {
-	foreach my $field (split(/\>/, $_)) {
-		$field =~ s/\>/\>\n/g;
-		$field =~ s/\<\/?\w+$//g;
-		if ($field =~ /^\s*$/) {
-			next;
-		}
-		if ($field =~ /^\//) {
-			$prefix = $field;
-			next;
-		}
-		print $prefix . $field . "\n";
-	}
-}

+ 0 - 1
plex-gui

@@ -1 +0,0 @@
-plex

+ 0 - 1
plex-playing

@@ -1 +0,0 @@
-plex

+ 0 - 1
plex-resolution

@@ -1 +0,0 @@
-plex

+ 0 - 1
plex-update

@@ -1 +0,0 @@
-plex

+ 0 - 27
plexMonitor/launchd/com.uberzach.plexMonitor.gui.plist

@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>UserName</key>
-	<string>tv</string>
-	<key>LimitLoadToHosts</key>
-	<array>
-		<string>beddy.uberzach.com</string>
-		<string>heady.uberzach.com</string>
-	</array>
-	<key>RunAtLoad</key>
-	<true/>
-	<key>Label</key>
-	<string>com.uberzach.plexMonitor.gui</string>
-	<key>KeepAlive</key>
-	<dict>
-		<key>NetworkState</key>
-		<true/>
-	</dict>
-	<key>ProgramArguments</key>
-	<array>
-		<string>/Users/tv/bin/video/plexMonitor/plexMonitor-gui</string>
-		<string>15</string>
-	</array>
-</dict>
-</plist>

+ 0 - 27
plexMonitor/launchd/com.uberzach.plexMonitor.playing.plist

@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>UserName</key>
-	<string>tv</string>
-	<key>LimitLoadToHosts</key>
-	<array>
-		<string>beddy.uberzach.com</string>
-		<string>heady.uberzach.com</string>
-	</array>
-	<key>RunAtLoad</key>
-	<true/>
-	<key>Label</key>
-	<string>com.uberzach.plexMonitor.playing</string>
-	<key>KeepAlive</key>
-	<dict>
-		<key>NetworkState</key>
-		<true/>
-	</dict>
-	<key>ProgramArguments</key>
-	<array>
-		<string>/Users/tv/bin/video/plexMonitor/plexMonitor-playing</string>
-		<string>0.25</string>
-	</array>
-</dict>
-</plist>

+ 0 - 1
plexMonitor/plexMonitor-gui

@@ -1 +0,0 @@
-plexMonitor.pl

+ 0 - 1
plexMonitor/plexMonitor-playing

@@ -1 +0,0 @@
-plexMonitor.pl

+ 0 - 104
plexMonitor/plexMonitor.pl

@@ -1,104 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-use LWP::Simple;
-use File::Basename;
-use Time::HiRes qw( usleep );
-use File::Temp qw( tempfile );
-
-# Prototypes
-sub xbmcHTTP($);
-
-# App config
-my $TEMP_DIR = `getconf DARWIN_USER_TEMP_DIR`;
-chomp($TEMP_DIR);
-my $DATA_DIR = $TEMP_DIR . '/plexMonitor';
-
-# xbmcHTTP commands
-my %CMDS = (
-	'PLAYING' => 'GetCurrentlyPlaying',
-	'GUI'     => 'GetGuiStatus'
-);
-
-# Debug
-my $DEBUG = 0;
-if ($ENV{'DEBUG'}) {
-	$DEBUG = 1;
-}
-
-# Command-line arguments
-my ($DELAY) = @ARGV;
-if (!$DELAY) {
-	$DELAY = 0;
-}
-$DELAY *= 1000000;    # Microseconds;
-
-# Sanity check
-if (!-d $TEMP_DIR) {
-	die("Bad config\n");
-}
-
-# Mode
-my $MODE = 'PLAYING';
-if (basename($0) =~ /GUI/i) {
-	$MODE = 'GUI';
-}
-
-# Add the data directory as needed
-if (!-d $DATA_DIR) {
-	mkdir($DATA_DIR);
-}
-
-# Loop forever (unless no delay is set)
-my $data     = '';
-my $dataLast = '';
-do {
-
-	# Run the monitor command
-	my $changed = 0;
-	$dataLast = $data;
-	$data     = xbmcHTTP($CMDS{$MODE});
-
-	# Compare this data set to the last
-	if ($data ne $dataLast) {
-		$changed = 1;
-		if ($DEBUG) {
-			print STDERR "Change detected in data:\n" . $data . "\n";
-		}
-	}
-
-	# If anything changed, save the data to disk
-	if ($changed) {
-		my ($fh, $tmp) = tempfile($DATA_DIR . '/' . $MODE . '.XXXXXXXX', 'UNLINK' => 0);
-		print $fh $data;
-		close($fh);
-		rename($tmp, $DATA_DIR . '/' . $MODE);
-	}
-
-	# Special handling for PLAYING mode -- it's a bit of a hack, but it saves a lot of code other places
-	if ($changed && $MODE eq 'PLAYING') {
-		my $playing = 0;
-		if ($data =~ /PlayStatus\:Playing/) {
-			$playing = 1;
-		}
-		my ($fh, $tmp) = tempfile($DATA_DIR . '/PLAY_STATUS.XXXXXXXX', 'UNLINK' => 0);
-		print $fh $playing . "\n";
-		close($fh);
-		rename($tmp, $DATA_DIR . '/PLAY_STATUS');
-	}
-
-	# Delay and loop
-	usleep($DELAY);
-} until ($DELAY == 0);
-
-# Exit cleanly
-exit(0);
-
-sub xbmcHTTP($) {
-	my ($cmd) = @_;
-	my $data = get('http://localhost:3000/xbmcCmds/xbmcHttp?command=' . $cmd);
-	if (!defined($data)) {
-		$data = '';
-	}
-	return $data;
-}

+ 0 - 29
projector/launchd/com.uberzach.projector.plist

@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>UserName</key>
-	<string>tv</string>
-	<key>LimitLoadToHosts</key>
-	<array>
-		<string>heady.uberzach.com</string>
-	</array>
-	<key>RunAtLoad</key>
-	<true/>
-	<key>Label</key>
-	<string>com.uberzach.projector</string>
-	<key>KeepAlive</key>
-	<dict>
-		<key>PathState</key>
-		<dict>
-			<key>/dev/tty.Projector-DevB</key>
-			<true/>
-		</dict>
-	</dict>
-	<key>ProgramArguments</key>
-	<array>
-		<string>/Users/tv/bin/video/projector/projector.pl</string>
-		<string>15</string>
-	</array>
-</dict>
-</plist>

+ 0 - 28
projector/launchd/com.uberzach.projector.power.plist

@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>UserName</key>
-	<string>tv</string>
-	<key>LimitLoadToHosts</key>
-	<array>
-		<string>heady.uberzach.com</string>
-	</array>
-	<key>RunAtLoad</key>
-	<true/>
-	<key>Label</key>
-	<string>com.uberzach.projector.power</string>
-	<key>KeepAlive</key>
-	<dict>
-		<key>OtherJobEnabled</key>
-		<dict>
-			<key>com.uberzach.projector</key>
-			<true/>
-		</dict>
-	</dict>
-	<key>ProgramArguments</key>
-	<array>
-		<string>/Users/tv/bin/video/projector/projectorPower.pl</string>
-	</array>
-</dict>
-</plist>

+ 0 - 1
projector/projector.pl

@@ -1 +0,0 @@
-../serial/serial.pl

+ 0 - 153
projector/projectorPower.pl

@@ -1,153 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-use IO::Socket::UNIX;
-use POSIX qw(ceil floor);
-
-# Prototypes
-sub mtime($);
-
-# Config
-my $TIMEOUT   = 900;
-my $COUNTDOWN = 300;
-
-# App config
-my $DELAY       = 60;
-my $CMD_TIMEOUT = 5;
-my $TEMP_DIR    = `getconf DARWIN_USER_TEMP_DIR`;
-chomp($TEMP_DIR);
-my $DATA_DIR = $TEMP_DIR . 'plexMonitor/';
-my $CMD_FILE = $DATA_DIR . 'PROJECTOR.socket';
-
-# Debug
-my $DEBUG = 0;
-if ($ENV{'DEBUG'}) {
-	$DEBUG = 1;
-}
-
-# Sanity check
-if (!-d $DATA_DIR || !-S $CMD_FILE) {
-	die("Bad config\n");
-}
-
-# Socket init
-my $sock = IO::Socket::UNIX->new(
-	'Peer'    => $CMD_FILE,
-	'Type'    => SOCK_DGRAM,
-	'Timeout' => $CMD_TIMEOUT
-) or die('Unable to open socket: ' . $CMD_FILE . ": ${@}\n");
-
-# State
-my $state      = 'INIT';
-my $stateLast  = $state;
-my $updateLast = time();
-my $projector  = 0;
-
-# Loop forever
-while (1) {
-
-	# Monitor the GUI and PLAYING files for changes only
-	{
-		my $mtime = mtime($DATA_DIR . 'PLAYING');
-		if ($mtime > $updateLast) {
-			$updateLast = $mtime;
-		}
-		$mtime = mtime($DATA_DIR . 'GUI');
-		if ($mtime > $updateLast) {
-			$updateLast = $mtime;
-		}
-	}
-
-	# Monitor the PROJECTOR file for state and changes
-	{
-		$projector = 0;
-		my $fh;
-		open($fh, $DATA_DIR . 'PROJECTOR')
-		  or die("Unable to open PROJECTOR\n");
-		my $text = <$fh>;
-		close($fh);
-		if ($text =~ /1/) {
-			$projector = 1;
-		}
-		if ($DEBUG) {
-			print STDERR 'Projector: ' . $projector . "\n";
-		}
-
-		my $mtime = mtime($DATA_DIR . 'PROJECTOR');
-		if ($mtime > $updateLast) {
-			$updateLast = $mtime;
-		}
-	}
-
-	# Calculate the new state
-	my $stateLast       = $state;
-	my $timeSinceUpdate = time() - $updateLast;
-	if ($DEBUG) {
-		print STDERR 'Time since update: ' . $timeSinceUpdate . "\n";
-	}
-	if ($state eq 'INIT') {
-		$state = 'COUNTDOWN';
-		if ($projector) {
-			$state = 'ON';
-		}
-	} elsif ($projector) {
-		if ($timeSinceUpdate > $TIMEOUT) {
-			$state = 'COUNTDOWN';
-			if ($timeSinceUpdate > $TIMEOUT + $COUNTDOWN) {
-				$state = 'OFF';
-			}
-		} else {
-			$state = 'ON';
-		}
-	} else {
-		if ($timeSinceUpdate < $TIMEOUT) {
-			$state = 'ON';
-		}
-	}
-
-	# If the state changed, do something about if
-	if ($state ne $stateLast) {
-		if ($DEBUG) {
-			print STDERR 'State change: ' . $stateLast . ' => ' . $state . "\n";
-		}
-		if ($state eq 'OFF') {
-
-			# Turn off the projector
-			$sock->send($state)
-			  or die('Unable to write command to socket: ' . $CMD_FILE . ': ' . $state . ": ${!}\n");
-		} elsif ($state eq 'ON') {
-
-			# Do nothing, at least for the moment
-		}
-
-	}
-
-	# Always announce a pending shutdown
-	if ($state eq 'COUNTDOWN') {
-		my $timeLeft = ($TIMEOUT + $COUNTDOWN) - $timeSinceUpdate;
-		$timeLeft = ceil($timeLeft / 60);
-
-		my $plural = 's';
-		if ($timeLeft == 1) {
-			$plural = '';
-		}
-		system('say', 'Projector powerdown in about ' . $timeLeft . ' minute' . $plural);
-	}
-
-	# Wait and loop
-	sleep($DELAY);
-}
-
-# Cleanup
-$sock->close();
-undef($sock);
-exit(0);
-
-sub mtime($) {
-	my ($file) = @_;
-	my $mtime = 0;
-	if (-r $file) {
-		(undef(), undef(), undef(), undef(), undef(), undef(), undef(), undef(), undef(), $mtime, undef(), undef(), undef()) = stat($file);
-	}
-	return $mtime;
-}

+ 0 - 42
serial/cmd.pl

@@ -1,42 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-use IO::Socket::UNIX;
-use POSIX qw(ceil floor);
-
-# App config
-my $TIMEOUT  = 5;
-my $TEMP_DIR = `getconf DARWIN_USER_TEMP_DIR`;
-chomp($TEMP_DIR);
-my $DATA_DIR = $TEMP_DIR . 'plexMonitor/';
-
-# Debug
-my $DEBUG = 0;
-if ($ENV{'DEBUG'}) {
-	$DEBUG = 1;
-}
-
-# Command-line parameters
-my ($DEV, $CMD) = @ARGV;
-my $CMD_FILE = $DATA_DIR . uc($DEV) . '.socket';
-
-# Sanity check
-if (!-d $DATA_DIR || !-S $CMD_FILE) {
-	die("Bad config\n");
-}
-
-# Socket init
-my $sock = IO::Socket::UNIX->new(
-	'Peer'    => $CMD_FILE,
-	'Type'    => SOCK_DGRAM,
-	'Timeout' => $TIMEOUT
-) or die('Unable to open socket: ' . $CMD_FILE . ": ${@}\n");
-
-# Send the command
-$sock->send($CMD)
-  or die('Unable to write command to socket: ' . $CMD_FILE . ': ' . $CMD . ": ${!}\n");
-
-# Cleanup
-$sock->close();
-undef($sock);
-exit(0);

+ 0 - 299
serial/serial.pl

@@ -1,299 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-use File::Basename;
-use File::Temp qw( tempfile );
-use IO::Select;
-use IO::Socket::UNIX;
-use Device::SerialPort;
-
-# Prototypes
-sub sendQuery($$);
-sub clearBuffer($);
-sub collectUntil($$);
-
-# Device parameters
-my ($DEV, $PORT, $CRLF, $DELIMITER, %CMDS, $STATUS_ON);
-if (basename($0) =~ /PROJECTOR/i) {
-	$DEV       = 'Projector';
-	$PORT      = '/dev/tty.' . $DEV . '-DevB';
-	$CRLF      = "\r\n";
-	$DELIMITER = ':';
-	%CMDS      = (
-		'INIT'   => '',
-		'ON'     => 'PWR ON',
-		'OFF'    => 'PWR OFF',
-		'STATUS' => 'PWR?'
-	);
-	$STATUS_ON = 'PWR=01';
-} elsif (basename($0) =~ /AMPLIFIER/i) {
-	$DEV       = 'Amplifier';
-	$PORT      = '/dev/tty.' . $DEV . '-DevB';
-	$CRLF      = "\r";
-	$DELIMITER = "\r";
-	%CMDS      = (
-		'INIT'     => '',
-		'ON'       => 'PWON',
-		'OFF'      => 'PWSTANDBY',
-		'STATUS'   => 'PW?',
-		'VOL+'     => 'MVUP',
-		'VOL-'     => 'MVDOWN',
-		'MUTE'     => 'MUON',
-		'UNMUTE'   => 'MUOFF',
-		'TV'       => 'SITV',
-		'DVD'      => 'SIDVD',
-		'SURROUND' => 'MSDOLBY DIGITAL',
-		'STEREO'   => 'MS7CH STEREO',
-
-	);
-	$STATUS_ON = 'PWON';
-} elsif (basename($0) =~ /TV/i) {
-	$DEV       = 'TV';
-	$PORT      = '/dev/tty.' . $DEV . '-DevB';
-	$CRLF      = "\r";
-	$DELIMITER = "\r";
-	%CMDS      = (
-		'INIT'      => 'RSPW1',
-		'ON'        => 'POWR1',
-		'OFF'       => 'POWR0',
-		'STATUS'    => 'POWR?',
-		'VOL+'      => 'MVUP',
-		'VOL-'      => 'MVDOWN',
-		'MUTE'      => 'MUTE1',
-		'UNMUTE'    => 'MUTE2',
-		'TV'        => 'IAVD0',
-		'PLEX'      => 'IAVD7',
-		'VOL_CHECK' => 'VOLM?',
-		'VOL6'      => 'VOLM6',
-		'VOL12'     => 'VOLM12',
-		'VOL24'     => 'VOLM24',
-		'VOL+'      => 'VOLM',
-		'VOL-'      => 'VOLM'
-	);
-	$STATUS_ON = '1';
-} else {
-	die("No device specified\n");
-}
-
-# App config
-my $DELAY_STATUS    = 5;
-my $BYTE_TIMEOUT    = 50;
-my $SILENCE_TIMEOUT = $BYTE_TIMEOUT * 10;
-my $MAX_CMD_LEN     = 1024;
-my $BT_CHECK        = $ENV{'HOME'} . '/bin/btcheck';
-my $TEMP_DIR        = `getconf DARWIN_USER_TEMP_DIR`;
-chomp($TEMP_DIR);
-my $DATA_DIR = $TEMP_DIR . 'plexMonitor/';
-my $CMD_FILE = $DATA_DIR . uc($DEV) . '.socket';
-
-# Debug
-my $DEBUG = 0;
-if ($ENV{'DEBUG'}) {
-	$DEBUG = 1;
-}
-
-# Command-line arguments
-my ($DELAY) = @ARGV;
-if (!$DELAY) {
-	$DELAY = 15;
-}
-
-# Sanity check
-if (!-r $PORT || !-d $DATA_DIR) {
-	die("Bad config\n");
-}
-
-# Wait for the serial port to become available
-system($BT_CHECK, $DEV);
-if ($? != 0) {
-	sleep($DELAY_STATUS);
-	die('Bluetooth device "' . $DEV . "\" not available\n");
-}
-
-# Socket init
-if (-e $CMD_FILE) {
-	unlink($CMD_FILE);
-}
-my $sock = IO::Socket::UNIX->new(
-	'Local' => $CMD_FILE,
-	'Type'  => SOCK_DGRAM
-) or die('Unable to open socket: ' . $CMD_FILE . ": ${@}\n");
-if (!-S $CMD_FILE) {
-	die('Failed to create socket: ' . $CMD_FILE . "\n");
-}
-my $select = IO::Select->new($sock)
-  or die('Unable to select socket: ' . $CMD_FILE . ": ${!}\n");
-
-# Port init
-my $port = new Device::SerialPort($PORT)
-  or die('Unable to open serial connection: ' . $PORT . ": ${!}\n");
-$port->read_const_time($BYTE_TIMEOUT);
-
-# Init (clear any previous state)
-sendQuery($port, $CMDS{'INIT'});
-
-# Track the power state
-# Check for new commands
-my $power      = -1;
-my $powerLast  = $power;
-my $lastStatus = 0;
-while (1) {
-
-	# Calculate our next timeout
-	# Hold on select() but not more than $DELAY_STATUS after our last update
-	# Plus 1 because we aren't using hi-res time
-	my $timeout = ($lastStatus + $DELAY_STATUS + 1) - time();
-	if ($timeout < 1) {
-		$timeout = 0;
-	}
-	if ($DEBUG) {
-		print STDERR 'Waiting for commands with timeout: ' . $timeout . "\n";
-	}
-
-	# Check for queued commands
-	my @ready_clients = $select->can_read($timeout);
-	foreach my $fh (@ready_clients) {
-
-		# Grab the inbound text
-		my $text = undef();
-		$fh->recv($text, $MAX_CMD_LEN);
-		$text =~ s/^\s+//;
-		$text =~ s/\s+$//;
-		if ($DEBUG) {
-			print STDERR 'Got command: ' . $text . "\n";
-		}
-
-		# Only accept valid commands
-		my $cmd = undef();
-		foreach my $name (keys(%CMDS)) {
-			if ($name eq $text) {
-				$cmd = $name;
-				last;
-			}
-		}
-
-		# Send command to serial device
-		if ($cmd) {
-			if ($DEBUG) {
-				print STDERR 'Sending command: ' . $cmd . "\n";
-			}
-			my $result = sendQuery($port, $CMDS{$cmd});
-			if ($DEBUG && $result) {
-				print STDERR "\tGot result: " . $result . "\n";
-			}
-		}
-	}
-
-	# Check the power state, but not too frequently
-	if (time() > $lastStatus + $DELAY_STATUS) {
-		$lastStatus = time();
-		$powerLast  = $power;
-		$power      = 0;
-		my $result = sendQuery($port, $CMDS{'STATUS'});
-		if ($result && $result eq $STATUS_ON) {
-			$power = 1;
-		}
-
-		# If something has changed, save the state to disk
-		if ($powerLast != $power) {
-			if ($DEBUG) {
-				print STDERR 'New ' . uc($DEV) . ' power state: ' . $power . "\n";
-			}
-			my ($fh, $tmp) = tempfile($DATA_DIR . uc($DEV) . '.XXXXXXXX', 'UNLINK' => 0);
-			print $fh $power . "\n";
-			close($fh);
-			rename($tmp, $DATA_DIR . uc($DEV));
-		}
-	}
-}
-
-# Cleanup
-undef($select);
-close($sock);
-undef($sock);
-$port->close();
-undef($port);
-exit(0);
-
-sub sendQuery($$) {
-	my ($port, $query) = @_;
-
-	# Read until the queue is clear (i.e. no data available)
-	# Since we don't have flow control this always causes one read timeout
-	$port->lookclear();
-	clearBuffer($port);
-
-	# Send the command
-	my $bytes = $port->write($query . $CRLF);
-	if ($DEBUG) {
-		print STDERR "\tWrote (" . $bytes . '): ' . $query . "\n";
-	}
-
-	# Wait for a reply (delimited or timeout)
-	return collectUntil($port, $DELIMITER);
-}
-
-sub clearBuffer($) {
-	my ($port) = @_;
-	my $byte = 1;
-	while (length($byte) > 0) {
-		$byte = $port->read(1);
-		if ($DEBUG && length($byte)) {
-			print STDERR "\tIgnored: " . $byte . "\n";
-		}
-	}
-}
-
-sub collectUntil($$) {
-	my ($port, $char) = @_;
-	if (length($char) != 1) {
-		die('Invalid collection delimiter: ' . $char . "\n");
-	}
-
-	# This byte-by-byte reading is not efficient, but it's safe
-	# Allow reading forever as long as we don't exceed the silence timeout
-	my $count  = 0;
-	my $string = '';
-	while ($count < $SILENCE_TIMEOUT / $BYTE_TIMEOUT) {
-		my $byte = $port->read(1);
-		if (length($byte)) {
-			$count = 0;
-			$string .= $byte;
-
-			if ($DEBUG) {
-				print STDERR "\tRead: " . $byte . "\n";
-			}
-
-			if ($byte eq $char) {
-				last;
-			}
-		} else {
-			$count++;
-		}
-	}
-
-	# Return undef if there was no data (as opposed to just a delimiter and/or whitespace)
-	if (length($string) < 1) {
-		if ($DEBUG) {
-			print STDERR "Read: <NO DATA>\n";
-		}
-		return undef();
-	}
-
-	# Translate CRLF and CR to LF
-	$string =~ s/\r\n/\n/g;
-	$string =~ s/\r/\n/g;
-
-	# Strip the trailing delimiter
-	$string =~ s/${char}$//;
-
-	# Strip leading or trailing whitespace
-	$string =~ s/^\s+//;
-	$string =~ s/\s+$//;
-
-	# Return our clean string
-	if ($DEBUG) {
-		print STDERR 'Read: ' . $string . "\n";
-	}
-	return $string;
-}