File:  [Paefchen] / ruby / snd / itunes2snd.rb
Revision 1.2: download - view: text, annotated - select for diffs - revision graph
Fri Apr 4 12:19:56 2008 UTC (16 years, 1 month ago) by as
Branches: MAIN
CVS tags: HEAD
- Default Lautstaerke parameter zugefuegt
- Es koennen mehr als ein SND angesprochen werden.
- Tracks werden ein und ausgefadet.
- Bei nicht kompatiplen Tracks zeigt das iTunes via Dialog an.

#!/usr/bin/env ruby
# $Paefchen: ruby/snd/itunes2snd.rb,v 1.2 2008/04/04 12:19:56 as Exp $

#
# Abhaengigkeiten
#
require 'rubygems'
require 'getoptlong'
require 'appscript'
require 'osax'
require 'snd'

# Externe Methoden laden
include Appscript
include OSAX


#
# Main-Object Variablen
#
@threads = []	# Abspiel-Threads
#@sockets = []	# Socket zum Sound-Chip
@snds = []		# Hosts wo abgespielt werden soll
@index = -1		# aktueller abspielender Track
@args =			# Aufrufsparameter
		{:port => 100, :usage => false, :volumen => false} 


# beim fehler wird der jeweilge Thread beendet
Thread.abort_on_exception = true


#
# main
#
def main
	# alle angegebenen SND-Chips durchegehen ..
	@snds.each do |snd|
		# .. und verbindung aufbauen
		begin
			snd[:socket] = TCPSocket.new snd[:host], snd[:port]
			snd[:setting] = SND::Setting.new snd[:host]
			if @args[:volumen]
				snd[:volumen] = @args[:volumen].to_i
			else
				snd[:volumen] = snd[:setting].volumen_get
			end
		rescue 
			puts "ConnectionError (#{snd[:host]}:#{snd[:port]}): " + $!
			sleep 2
			retry
		end
	end

	listen_on_itunes
end


#
# usage
#
def usage
	puts "usage: #{$0} [--port|-p <port>, --volumen|-v <0-250>] <host1[:<port>]> [<host2[:<port>]> [<host3..]]"
	exit 0
end


#
# Gibt ein Dialog in iTunes aus
#
def dialog text
	osax(nil, 'iTunes').display_dialog text, {:buttons => 'OK'}
end


#
# iTunes "abhoehren"
# ( umgesetzt via pooling )
#
def listen_on_itunes
	while true
		sleep 1

		itunes = app('iTunes')
		# wenn itunes nicht spielt machen wir auch nichts
		next if itunes.player_state.get != :playing

		# aktuelle Track-ID die iTunes spielt
		current_index = itunes.current_track.index.get

		# wenn es nicht mehr der Track zuvor ist,
		# den neuen abspielen.
		if current_index != @index
			play_new_track itunes.current_track
			@index = current_index
		end
	end
end


#
# Track abspielen
#
def play_new_track track
	file = track.location.get.to_s

	# Der Soundchip vertraegt nur MP3-Streams.
	# daher lassen wir, wenn es keine MP3 ist, alles wie es ist.
	if ! /\.mp3$/i.match file
		dialog "SND-Fehler: #{track.name.get} kann nicht abgespielt werden da es keine MP3-Datei ist."
		puts "error => #{track.name.get} ist keine MP3-Datei"
		return false
	end
	
	puts "play => #{track.name.get}"
	
	# alle Threads durchgehen und wenn einer noch laeuft
	# volumen runterpegeln und beenden
	@threads.each do |thread|
		snd = thread[:snd]
		Thread.new { snd[:setting].volumen_fadeto 150 }
		Thread.kill thread
	end

	# alle sockets durchgehen, volumen hochdrehen  und neue Daten
	# drauf schicken das ganze jeweils in einem eigenen Thread um
	# das ganze zu paralelisieren und weiter iTunes abzuhoeren zu koennen.
	@snds.each do |snd|
		thread = Thread.new do
			File.open(file, 'r') do |fh|
				begin
					Thread.new do
						sleep 4 # mit der wartezeit tricksen wir den Cach aus
						snd[:setting].volumen_fadeto snd[:volumen]
					end
					snd[:socket].puts fh.read
				rescue
					puts "SndError: " + $!
					sleep 1
					retry
				end
			end
		end
		thread[:snd] = snd
		@threads << thread
	end
end


# Parameter abfragen und parsen
begin
	GetoptLong.new(
				['--help',		'-h',	GetoptLong::NO_ARGUMENT],
				['--port',		'-p',	GetoptLong::REQUIRED_ARGUMENT],
				['--volumen',	'-v',	GetoptLong::REQUIRED_ARGUMENT]
	).each do |arg, value|
		@args[arg[2..-1].to_sym] = value
	end
rescue
	exit 1
end

# wenn hilfe
usage if @args[:help]

# Hosts aus den uebrigen Argumenten rausparsen
ARGV.each do |snd|
	args = snd.split ':'
	snd = {:host => args[0]}
	if args.length < 2
		snd[:port] = @args[:port]
	else
		snd[:port] = args[1]
	end
	@snds << snd
end

# wenn kein Host angegeben ist
if @snds.length < 1
	puts "Error: Missing host arguments (try --help)"
	exit 1
end

# los geht's
main