[Hardcorescript] Zeitgesteuerte Aufnahme eines Streams

Skeeve

Pomme d'or
Registriert
26.10.05
Beiträge
3.120
Dieses Script ist aufgrund dieses Threads entstanden.

Achtung! Ich denke, das ist keine "leichte Scriptkost"! Sobald "CloneOfMyself" wieder online ist, werde ich ihn bitten, das Script auf seine Seiten zu übernehmen. Dort wird es dann auch weitergepflegt werden. Bis dahin stelle ich es hier schonmal ein um jetzt schon Rückmeldungen zu erhalten, was verbessert werden kann.

Das Script benötigt zwingend den MPlayer und ist hier für die PPC Version vorkonfiguriert. Bitte gegebenenfalls entsprechend für Intel anpassen.

Dazu den Quelltext in den ScriptEditor übernehmen und nach Anpassung als script (streamdump.scpt) speichern.

Anschließend müßt Ihr einen Kalender "streamdump" anlegen und darin ein Ereigniss mit beliebigem Namen.

Als URL tragt Ihr die URL des Streams ein.

Als Ort den gewünschten Speicherort.

Als Erinnnerung wird dieses Script eingetragen.

Mehr Informationen sind in den Kommentaren des Scripts zu finden.

Code:
(*
streamdum V0.1 (C) 2007 by Skeeve 
mail to streamdump.question.skeeve et xoxy.net
use it at your own risk use it however you like but don't sell it

This schript is intended to be invoked by an iCal event in order to record the stream of an internet radio.

If this script is run "by hand", it uses the last event it can find to record a stream. So take care...

Setting things up:

1) Create a calendar called "streamdump" or whatever you will define below as the calendar's name. This need only be done once

2) Create an event in that calendar and set start and end time of event to match the start end end of the broadcast

3) Set the summary (title) of the event to whatever you like. It isn't used.

4) Set the URL of the event to the URL of the broadcast.
	Note: Currently only http:// is supported because I don't know whether or not others do work as easily.
	Your input is welcome.

5) Set the location of the event to the filename you want to be created. 
	
	Placeholders in the filename are:
	Any number of hashes ('##') will will be replaced by the sequence number of the event, giving you an effective means to have a counter in the filename.
	Example: /my/recording###.mp3
	could become: /my/recording004.mp3
	
	Should there be a % in the filename, the whole filename is treated as a format string to the date command, giving you an effective means to have the current date and time in the filename.
	Example: /my/recording###_%g-%m-%d_%H-%M.mp3
	could become: /my/recording005_07-12-31_23-55.mp3
	For further reference open the terminal and enter
		man strftime
	or read online
		http://developer.apple.com/DOCUMENTATION/Darwin/Reference/ManPages/man3/strftime.3.html
	
	Should the filename not start with "/" it is expanded relative to your home directory
	Example: /my/recording.mp3
	will be unchanged
	Example: my/recording.mp3
	will become: /Users/Skeeve/my/recording.mp3
*)

-- this is the name your calendar must have
property my_calendar_name : "streamdump"

-- You absolutely need to install MPlayer.
-- Mine is "MPlayer OSX PPC"
-- inside the package you will find the
-- mplayer executable. It's path name need to
-- be changed here, should it change in the
-- a future release!
-- I used MPlayer OS X 1.0rc1
-- from http://www.mplayerhq.hu/design7/dload.html
-- so you should be fine if you use the same.
property mplayer : (POSIX path of ((path to application "MPlayer OSX PPC") as string)) & "Contents/Resources/External_Binaries/mplayer_ppc.app/Contents/MacOS/mplayer"

-- You shouldn't need to change anything here
property mplayer_call : {¬
	"%mplayer", ¬
	"-noconsolecontrols", ¬
	"-really-quiet", ¬
	"-dumpaudio", ¬
	"-dumpfile", ¬
	"%filename", ¬
	"%url"}

-- nor here
property cmd_curl : {¬
	"/usr/bin/curl", ¬
	"--silent", ¬
	"%url"}

property cmd_date : {¬
	"/bin/date", ¬
	"+%filename"}

property cmd_osascript : "/usr/bin/osascript"

property NL : ASCII character 10

on run
	try -- is mplayer available
		tell application "Finder" to set mplayer_path to (POSIX file mplayer) as alias
	on error -- NO!
		display alert "MPlayer not found" message "MPlayer is expected at «" & POSIX file mplayer & "»" & return & return & "You need to set the path to MPlayer in this script!" as critical
		return
	end try
	--
	tell application "iCal"
		-- find the event calendar name is fixed!
		set my_calendar to first calendar whose title is my_calendar_name
		set this_event to (last event of my_calendar)
		
		-- get the end date
		set ed to (end date of this_event)
		
		-- how long do we want to record?
		set len_in_seconds to (time of ed) - (time of (current date))
		
		-- Negative? So it goes past midnight!
		if len_in_seconds < 1 then set len_in_seconds to len_in_seconds + 1 * days
		
		-- episode
		set episode to sequence of this_event
		
		-- url
		set the_url to url of this_event
		
		-- filename
		set the_filename to location of this_event
		
		-- calendarid
		set calendarid to uid of my_calendar
		
		-- eventid
		set eventid to uid of this_event
		
	end tell
	
	-- parameter preparation
	set the_parameters to {¬
		a reference to calendarid, ¬
		a reference to eventid, ¬
		a reference to len_in_seconds, ¬
		a reference to episode, ¬
		a reference to the_filename, ¬
		a reference to the_url, ¬
		a reference to mplayer}
	
	-- parameter check
	if the_url does not start with "http://" then
		display alert "URL wrong" message "The url was «" & the_url & "»" as critical
		return
	end if
	if the_url ends with ".m3u" then
		set the_url to first paragraph of system(cmd_curl, the_parameters)
	end if
	
	set the_filename to first paragraph of perl("
		for ($param{'filename'}) {
			s/(#+)/sprintf('%0'.length($1).'d', $param{'episode'})/ge;
			s#^([^/])#$ENV{'HOME'}/$1#;
			print $_
		}", the_parameters)
	
	if the_filename contains "%" then
		set the_filename to first paragraph of system(cmd_date, the_parameters)
	end if
	
	if the_filename is "" then
		display alert "Filename is empty" message "Did you forget to set the location of the event?" as critical
		return
	end if
	
	-- now start recording
	set recording to first paragraph of perl("
		# backgrounding the child
		my $pid;
		FORK: {
			if ( $pid = fork ) {
				print 'Recording to «',$param{'filename'},qq(\\n);
				exit;
			}
			if ( defined $pid ) {
				close STDIN;
				close STDOUT;
				close STDERR;
			}
			else {
				die qq(Couldn't fork\\n);
			}
		}

		# Here the background process runs
		open(STDERR, '>/dev/console') or die;
		open(STDOUT, '>/dev/null') or die;
		FORK: {
			if ( $pid = fork ) {
				$SIG{'ALRM'}= sub {	kill 'TERM',$pid; };
				alarm $param{'seconds'};
				waitpid $pid,0;
				my $too_early= alarm 0;
				my $recording= qq<Last recording in > . $param{'filename'};
				if ($too_early) {
					$recording.= qq< (Stream ended ${too_early}sec too early)>;
				}
				system '" & cmd_osascript & ¬
		"','-e',qq<tell application \"iCal\" to set description of first event of (first calendar whose uid is \"" & ¬
		calendarid & "\") whose uid is \"" & ¬
		eventid & "\" to \"$recording\">;
			}
			elsif ( defined $pid ) {
				exec @params;
				die join(' ', q<Couldn't exec>, @params, q<:>,$!);
			}
			else {
				die qq<Couldn't fork\\n>;
			}
		}", ¬
		the_parameters & mplayer_call)
	tell application "iCal"
		set description of this_event to recording
	end tell
end run

on system(command, parameters)
	do shell script "perl <<-'" & (ASCII character 3) & "'
	use strict;
	use warnings;" & perl_params() & "
	system @params;
	__DATA__" & NL & join(NL, parameters & command)
end system

on perl(commands, parameters)
	do shell script "perl -<<'" & (ASCII character 3) & "'
	use strict;
	use warnings;" & perl_params() & commands & "
	__DATA__" & NL & join(NL, parameters)
end perl

on perl_params()
	return "
	my (%param, @params);
	# read parameters from DATA-Section
	(@param{qw(
		calendarid
		eventid
		seconds
		episode
		filename
		url
		mplayer
		)}, @params)= map { tr/\\015\\012//d; $_ } <DATA>;
	foreach (@params) {
		s/%(\\w+)\\b/$param{$1}/g;
	}"
end perl_params

on join(joiner, a_list)
	set j to ""
	set str to ""
	repeat with elt in a_list
		set str to str & j & elt
		set j to joiner
	end repeat
	return str
end join