#!/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 , --volumen|-v <0-250>] ]> []> [ '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