USB Syncing

From XPUB & Lens-Based wiki

A first prototype on a debian laptop:

import os, time

initial = set(os.listdir("/media"))

while True:
    media = set(os.listdir("/media"))
    new = media.difference(initial)
    if (len(new) == 2):
        sticks = list(new)
        print "TIME TO SYNC"
        os.system("mplayer -loop 0 sticksync/sync.ogg &")

        # rsync 0 => 1
        cmd = "rsync -rv /media/{0}/ /media/{1}/ ".format(sticks[0], sticks[1])
        print cmd
        os.system(cmd)

        # rsync 1 => 0
        cmd = "rsync -rv /media/{1}/ /media/{0}/ ".format(sticks[0], sticks[1])
        print cmd
        os.system(cmd)
        os.system("killall mplayer")

        while True:
            print "waiting for less than two sticks"
            media = set(os.listdir("/media"))
            new = media.difference(initial)
            if (len(new) < 2):
                break
            time.sleep(1)

        # os.system(cmd)
    else:
        print "nothing to do"

    time.sleep(1)

https://archive.org/details/EqueTheartoflisteningSync

Auto login on pi: http://stackoverflow.com/questions/17830333/start-raspberry-pi-without-login

Getting it to work on a PI

Getting it to work on a pi required some altering. First we needed to install the usbmount package.

  sudo apt-get install usbmount

This however creates a set of /media/usb0, /media/usb1 mount points that are always there. So we can't simply check to see if new file names exist. The fix is to alter the usbmount options to make sure that the auto-mounted files are owned by the "pi" user, and then to filter the list to only check those owned by pi (aka uid 1000).

import os, time

def check ():
    files = os.listdir("/media")
    files = [x for x in files if os.stat("/media/"+x).st_uid == 1000]
    return files

def do(cmd):
    print cmd
    os.system(cmd)

while True:
    sticks = check()
    print sticks
    if (len(sticks) == 2):
        print "TIME TO SYNC"
        do("aplay sticksync/syncing.wav")
        do("mplayer -loop 0 sticksync/sync.ogg &")

        # rsync 0 => 1
        cmd = "rsync -rv /media/{0}/ /media/{1}/ ".format(sticks[0], sticks[1])
        do(cmd)
        # rsync 1 => 0
        cmd = "rsync -rv /media/{1}/ /media/{0}/ ".format(sticks[0], sticks[1])
        do(cmd)

        do("pumount /media/{0}".format(sticks[0]))
        do("pumount /media/{0}".format(sticks[1]))
        do("killall mplayer")

        while True:
            print "waiting for less than two sticks"
            sticks = check()
            if (len(sticks) < 2):
                break
            time.sleep(1)

    else:
        print "nothing to do"

    time.sleep(1)

sudo nano /etc/usbmount/usbmount.conf

...
MOUNTOPTIONS="noexec,nodev,noatime,nodiratime"
FS_MOUNTOPTIONS="-fstype=vfat,uid=pi,gid=pi,umask=0"
...

NB: it was necessary to put -fstype=vfat. Despite the expectation that if you remove -fstype it would apply to ALL file types, it seems not to actually work!

For auto-login as pi, a single line change to /etc/inittab (oeps this seems the unchanged file... to do...)

/etc/inittab

# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $

# The default runlevel.
id:2:initdefault:

# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS

# What to do in single-user mode.
~~:S:wait:/sbin/sulogin

# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.

l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin

# What to do when CTRL-ALT-DEL is pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now

# Action on special keypress (ALT-UpArrow).
#kb::kbrequest:/bin/echo "Keyboard Request--edit /etc/inittab to let this work."

# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop

# /sbin/getty invocations for the runlevels.
#
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
#
# Format:
#  <id>:<runlevels>:<action>:<process>
#
# Note that on most Debian systems tty7 is used by the X Window System,
# so if you want to add more getty's go ahead but skip tty7 if you run X.
#
1:2345:respawn:/sbin/getty 38400 tty1
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4
5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6

# Example how to put a getty on a serial line (for a terminal)
#
#T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100

# Example how to put a getty on a modem line.
#
#T3:23:respawn:/sbin/mgetty -x0 -s 57600 ttyS3