1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
#!/usr/bin/python
import os
import usb1
import libnetmd
from time import sleep
import platform
import subprocess
def main(bus=None, device_address=None, ext='ogg', track_range=None, title=None):
context = usb1.LibUSBContext()
for md in libnetmd.iterdevices(context, bus=bus,
device_address=device_address):
md_iface = libnetmd.NetMDInterface(md)
try:
MDDump(md_iface, ext, track_range, title)
finally:
md_iface.stop()
def getTrackList(md_iface, track_range):
result = []
append = result.append
track_count = md_iface.getTrackCount()
if isinstance(track_range, tuple):
min_track, max_track = track_range
if max_track is None:
max_track = track_count - 1
assert max_track < track_count
assert min_track < track_count
track_list = xrange(min_track, max_track + 1)
elif isinstance(track_range, int):
assert track_range < track_count
track_list = [track_range]
else:
track_list = xrange(track_count)
for track in track_list:
hour, minute, second, sample = md_iface.getTrackLength(track)
codec, channel_count = md_iface.getTrackEncoding(track)
channel_count = libnetmd.CHANNEL_COUNT_DICT[channel_count]
ascii_title = md_iface.getTrackTitle(track)
wchar_title = md_iface.getTrackTitle(track, True).decode('shift_jis')
title = wchar_title or ascii_title
append((track,
(hour, minute, second, sample),
str(channel_count),
title))
return result
def MDDump(md_iface, ext, track_range, disk_title_override=None):
if disk_title_override is None:
ascii_title = md_iface.getDiscTitle()
wchar_title = md_iface.getDiscTitle(True).decode('shift_jis')
disc_title = wchar_title or ascii_title
else:
disc_title = disk_title_override
if disc_title == '':
directory = '.'
else:
directory = disc_title;
print 'Storing in ', directory
if not os.path.exists(directory):
os.mkdir(directory)
for track, (hour, minute, second, sample), channels, title in \
getTrackList(md_iface, track_range):
duration = '%02i:%02i:%02i.%03i' % (hour, minute, second, sample/.512)
filename = '%02i - %s.%s' % (track + 1, title, ext)
print 'Recording', filename, '(', duration, ')'
md_iface.gotoTrack(track)
# Attemp to reduce the MD play delay by...
print 'Waiting for MD...'
# ...starting to play (some devices start their seek at this
# time, others already at gotoTrack)...
md_iface.play()
# ... wait until playing really begins ... (waits until the second
# second of audio playing)
while md_iface.getPosition()[0:4] != [track, 0, 0, 1]:
print md_iface.getPosition()
sleep(0.25)
# ... pause and go back to track beginning.
md_iface.pause()
md_iface.gotoTrack(track)
if platform.system() == 'Windows':
sox = 'sox.exe'
else:
sox = 'sox'
start_sox = [sox,
'-d',
'-S',
'-c', channels,
'%s/%s' % (directory, filename),
'silence', '1', '0.1', '0.1%',
'trim', '0', duration,
]
pid = subprocess.Popen(start_sox)
md_iface.play()
sleep(((hour * 60 + minute) * 60) + second)
while md_iface.getPosition()[0] == track:
sleep(1)
md_iface.pause()
print 'Done, waiting for sox to return...'
pid.wait()
# TODO: generate playlists based on groups defined on the MD
print 'Finished.'
if __name__ == '__main__':
from optparse import OptionParser
parser = OptionParser()
parser.add_option('-b', '--bus')
parser.add_option('-d', '--device')
parser.add_option('-t', '--track-range')
parser.add_option('-T', '--title')
(options, args) = parser.parse_args()
assert len(args) < 2
if len(args) == 1:
ext = args[0]
else:
ext = 'ogg'
track_range = options.track_range
if track_range is not None:
if '-' in track_range:
begin, end = track_range.split('-', 1)
if begin == '':
begin = 0
else:
begin = int(begin) - 1
if end == '':
end = None
else:
end = int(end) - 1
assert begin < end
track_range = (begin, end)
else:
track_range = int(track_range) - 1
main(bus=options.bus, device_address=options.device, ext=ext,
track_range=track_range, title=options.title)
|