#!/usr/bin/ruby -w require 'optparse' require 'ostruct' require 'xmms' require 'fileutils' class Optparse PROGRAM = $0.sub(/^.*\//, '') USAGE_BANNER = "Usage: #{PROGRAM} [options]" def self.parse(args) options = OpenStruct.new options.append = nil options.copy = nil options.format = :pls options.dos = false options.streams = true options.strip = nil opts = OptionParser.new do |opts| opts.banner = USAGE_BANNER opts.on("-a", "--append PATH", "Append leading path to file-names.") do |path| options.append = path end opts.on("-c", "--copy PATH", "Copy files while creating playlist.") do |path| options.copy = path end opts.on("-d", "--dos", "Translate file paths to DOS/Windows format.") do options.dos = true end opts.on("-f", "--format FORMAT", [:m3u, :pls], "Format for output: m3u or pls") do |format| options.format = format end opts.on("-n", "--no-streams", "Omit streams from playlist.") do options.streams = false end opts.on("-s", "--strip PATH", "Strip leading path from file-names.") do |path| options.strip = path end opts.on_tail("-h", "--help", "Show this message.") do puts opts puts <<'EOF' Example: xmms2pl -a /music -c /mnt/ihp/music -df m3u -n -s /var/local/audio Connect to XMMS and copy files in the dynamic playlist to /mnt/ihp. In the process, /var/local/audio will be stripped from the source filename and /music will be appended to it, so that /var/local/audio/artist/song.ogg will be copied to /mnt/ihp/music/artist/song.ogg. The associated playlist path will be \music\artist\song.ogg, thanks to DOS/Windows translation. An M3U format playlist will be output, but any streams in the original will be omitted from it. Be aware that, if you're creating a playlist for a device like an iRiver jukebox, you'll need to send the output through a program like unix2dos, in order to get DOS/Windows-style line endings. EOF exit end end begin opts.parse!(args) options rescue OptionParser::InvalidOption puts opts exit 1 end end end options = Optparse.parse(ARGV) # Connect to XMMS and grab play-list # remote = Xmms::Remote.new playlist = remote.playlist # Strip streams if desired (streams have a time of -1) # playlist.delete_if { |tune| tune[2] == -1 } if options.copy || ! options.streams # Display file header # if options.format == :m3u puts "#EXTM3U" else printf("[playlist]\nNumberOfEntries=%d\n", playlist.size) end # Iterate over play-list # count = 0 playlist.each do |tune| name, path, time = tune file = path.dup base = File.basename(file) # Strip leading path if desired # path.sub!(/^#{options.strip}/, '') unless options.strip.nil? src_dir = File.dirname(path) if options.copy dst_dir = File.join(options.copy, src_dir[1..-1]) FileUtils.mkdir_p dst_dir unless File.exist? dst_dir FileUtils.cp file, dst_dir unless File.exist? File.join(dst_dir, base) end # Append leading path if desired # path = options.append + path unless options.append.nil? # Translate file-names if desired # path.tr!('/', '\\') if options.dos if options.format == :m3u printf("#EXTINF:%d,%s\n%s\n", time / 1000, name, path) else printf("File%d=%s\n", count += 1, path) end end