I am becoming a bit of a cycling enthusiast. Rather surprising at age 48. It’s not my first encounter with cycling, but it seems to have become my most intimate. I think it is about time to get something on the record. It is just my most recent episode of cycling. There have been many others over years.
EyeTV RecordingDone script, my take.
It is now more or less six years since I began watching telly exclusively using eyeTV running on my mac. To this day I have not found a better PVR, and I have tried a few. It has its niggles and features, but I am largely satisfied with its functionality. With ever larger screens available, it allows me to browse and watch telly at the same time. In fact it allows me to do whatever I am doing whilst watching telly in a small window. Sometimes I just use it the way I would a telly, with remote control and all. My current set up runs on a 2011 mac mini, using two Elgato DTT tuners. This allows me to record two programs simultaneously, or watch one and record on the other. I tend to record everything I want to watch. This way, I can pretty much avoid advertising, by never watching real-time (although limits the possibility of joining the twitter debate).
Prior to eyeTV 3, the downside was always having to leave the machine running, so as not to miss recording. The advent of eyeTV brought triggered scripts, whereby a script could be initiated on completion of a recording. Various RecordingDone scripts became available for download. I duly installed one of these, which would trigger after any program was recorded and if no other recording was in progress, it would sleep or close down the machine. It was now possible to save a bit of electricity usage, and remain confident that I wouldn’t miss any recordings.
The following is a common example:
on RecordingDone(recordingID) set isCurrentlyRecording to check_eyetv_is_recording() if isCurrentlyRecording is false then with timeout of 300 seconds tell me to activate display dialog "Warning: EyeTV has now finished recording and the system will automatically shut down in 5 minutes unless you click Stop!" with icon 2 buttons {"Stop!"} giving up after 300 default button "Stop!" set theresults to the result if gave up of theresults is true then tell application "System Events" to sleep end if end timeout else quit end if end RecordingDone to check_eyetv_is_recording() delay 30 tell application "EyeTV" if is_recording then return true else return false end if end tell end check_eyetv_is_recording
After a short while, I noticed a number of issues with this script. Often if I was browsing, whilst a recording came to an end, the dialog box may end up in the back ground and un noticed, so that the machine would just shut down whilst I continued to browse. Sometimes if two programs were recording, and ended simultaneously, one instance of the script would be un noticed so the machine would shut down. The only solution was to just get on and learn a bit of AppleScript and fix all the problems. So here is my solution, and also my first AppleScript. Try it if you wish.
So, what have you done with a 400 line script that couldn’t be done in 26? I hear you all ask.
Essentially I wanted to achieve the following:
- Only allow one instance of the script to run at any one time
- Log everything the script was up to
- Avoid a shutdown failure if Firefox was taking too long to quit (which it often does if you use Xmarks)
- Prevent the script from changing (or offering to change) the machine state if I was busy doing other things, such as
- Browsing
- Watchning EyeTV in full screen mode
- Watching Quicktime movie
- Listening to itunes
- Watching a DVD
So, you may think it is cumbersome, but it works for me. The code may not be the best AppleScript you ever saw, and there may be better ways of doing things, but It is my first go at AppleScript.
For those who have never used a RecordingDone script before, all you have to do, is copy the below code, and paste it into a new text file (use text editor if you like). Save the file with the name RecordingDone.scpt in nameofyourharddrive/Library/Application Support/EyeTV/Scripts/TriggeredScripts. (Create this folder if it doesn’t already exist).
Job done.
--originally written by Brendan Ratcliffe 2011 myredroom.wordpress.com global LogMsg global posixLogFileName, fullLogFileName, fullFileName, posixFileName global recordingNow, idletime, otherInstance global currentRecordingID, thisRecordingTitle, referenceNumber global itunesRunning, quicktimeRunning, DVDrunning, firefoxrunning global itunesPlaying, quicktimePlaying, DVDplaying global timeNow, nowPlus15Mins, nowPlus60Mins, soonestrecordingStart, soonestrecordingtitle on RecordingDone(recordingID) set currentRecordingID to recordingID --save for later my initLogFile() --set up log file set errNum to 0 set itemno to 1 tell application "EyeTV" repeat with recid in unique ID of every recording if recid as text is equal to recordingID as text then set mytitle to title of item itemno of every recording my writetolog("RecordingDone script has been invoked, having completed recording (" & mytitle & ").") end if set itemno to itemno + 1 end repeat end tell set anotherInstance to my check_for_another_instance() if anotherInstance then return end if set idletime to (do shell script "ioreg -c IOHIDSystem | perl -ane 'if (/Idle/) {$idle=(pop @F)/1000000000; print $idle,\"\";last}'") my writetolog("The system has been idle for: " & idletime & " seconds.") try set realidletime to idletime as real on error my writetolog("error occurred in line: \"" & "set realidletime to idletime as real" & "\"") my deleteSwitchFile() return end try try set intidletime to round realidletime as integer on error my writetolog("error occurred in line: \"" & "set intidletime to round realidletime as integer" & "\"") my deleteSwitchFile() return end try tell application "EyeTV" if is_recording = true then my writetolog("eyeTV is currently recording another program. Therefore the machine state will not be altered.") my deleteSwitchFile() return end if --if playing is true and full screen is true then if full screen is true then --altered to handle bug in 3.5.4 my writetolog("eyeTV is currently playing in full screen mode. Therefore the machine state will not be altered.") my deleteSwitchFile() return end if if playing is true and full screen is false then my writetolog("eyeTV is currently playing in a window.") if intidletime < 120 then my writetolog("eyeTV is currently playing in a window, but there has been user activity in the last 2 minutes. Therefore the machine state will not be altered.") my deleteSwitchFile() return end if end if if playing is false then my writetolog("eyeTV is not currently playing at all.") if intidletime < 120 then my writetolog("eyeTV is not currently playing, but there has been user activity in the last 2 minutes. Therefore the machine state will not be altered.") my deleteSwitchFile() return end if end if set timeNow to current date set nowPlus15Mins to (current date) + 15 * minutes set nowPlus60Mins to (current date) + 60 * minutes set soonestrecordingStart to (current date) + 1 * days my writetolog("Now searching for future recordings between now and " & soonestrecordingStart & ".") set itemno to 1 repeat with thisRecordingStart in start time of every program if thisRecordingStart > timeNow and thisRecordingStart < soonestrecordingStart then set soonestrecordingStart to thisRecordingStart set soonestrecordingtitle to title of item itemno of every program end if set itemno to itemno + 1 end repeat if soonestrecordingStart ≥ nowPlus15Mins then my writetolog("The soonest future recording (" & soonestrecordingtitle & ") will begin at " & soonestrecordingStart & ".") else my writetolog("eyeTV is scheduled to start another recording within the next 15 minutes (" & soonestrecordingtitle & ").") my writetolog("Therefore the machine state will not be altered.") my deleteSwitchFile() return end if end tell --at this point there may be good reason to offer sleep, --so lets do some more tests to determine what is going on on this system --if the eyeTV is in full screen, but paused then lets offer sleep/shutdown --now we will work out whether the system has other media player running tell application "System Events" set itunesRunning to (name of processes) contains "iTunes" set quicktimeRunning to (name of processes) contains "Quicktime Player" set DVDrunning to (name of processes) contains "DVD Player" set firefoxrunning to (name of processes) contains "Firefox" end tell if itunesRunning is true then tell application "iTunes" if player state is playing then set itunesPlaying to true my writetolog("iTunes has been found to be running and playing. Therefore the machine state will not be altered.") my deleteSwitchFile() return else set itunesPlaying to false my writetolog("iTunes has been found to be running but not playing. ") ignoring application responses quit end ignoring end if end tell else set itunesPlaying to false my writetolog("iTunes has been found not to be running. ") end if if quicktimeRunning is true then tell application "QuickTime Player" if exists document 1 then my writetolog("Quicktime has been found to be running.") set quicktimePlaying to false repeat with thisWindowActive in playing of every document if thisWindowActive is true then set quicktimePlaying to true my writetolog("Quicktime has been found to be running and playing. Therefore the machine state will not be altered.") my deleteSwitchFile() return end if end repeat else set quicktimePlaying to false my writetolog("Quicktime has been found to be running but not playing. ") ignoring application responses quit end ignoring end if end tell else set quicktimePlaying to false my writetolog("Quicktime has been found not to be running. ") end if if DVDrunning is true then tell application "DVD Player" if dvd state is playing then set DVDplaying to true my writetolog("DVD Player has been found to be running and playing. Therefore the machine state will not be altered.") my deleteSwitchFile() return else set DVDplaying to false my writetolog("DVD Player has been found to be running but not playing. ") ignoring application responses quit end ignoring end if end tell else set DVDplaying to false my writetolog("DVD Player has been found not to be running. ") end if my writetolog("Completed checks for other active players.") if soonestrecordingStart > nowPlus15Mins and soonestrecordingStart < nowPlus60Mins then my writetolog("got into first idle check check") (beep 2) activate set thisResponse to display dialog "EyeTV has just finished recording. Another recording will begin within the next hour. Would you like the computer to go into sleep mode?" buttons {"Yes", "No"} default button "No" with icon note with title "EyeTV-Recorder" giving up after 30 if button returned of thisResponse = "" then my deleteSwitchFile() my writetolog("System sent to sleep because no response to sleep dialog.") tell application "Finder" ignoring application responses sleep end ignoring return end tell end if if button returned of thisResponse = "Yes" then my deleteSwitchFile() my writetolog("System sent to sleep because user responded \"Yes\" to sleep dialog.") tell application "Finder" ignoring application responses sleep end ignoring return end tell end if if button returned of thisResponse = "No" then my deleteSwitchFile() my writetolog("System state unaltered because user responded \"No\" to sleep dialog.") return end if else if soonestrecordingStart > nowPlus60Mins then --my writetolog("got into second idle check.") beep 2 activate set thisResponse to display dialog "EyeTV has just finished recording. There are no scheduled recordings in the next hour. Would you like the computer shut down?" buttons {"Yes", "Sleep", "No"} default button "No" with icon note with title "EyeTV-Recorder" giving up after 30 if button returned of thisResponse = "Yes" then if firefoxrunning is true then my quitFirefox() end if my deleteSwitchFile() my writetolog("System shutdown because user responded \"Yes\" to shutdown dialog.") tell application "Finder" ignoring application responses shut down end ignoring return end tell end if if button returned of thisResponse = "" then if firefoxrunning is true then my quitFirefox() end if my deleteSwitchFile() my writetolog("System shut down because no response to shutdown dialog.") tell application "Finder" ignoring application responses shut down end ignoring return end tell end if if button returned of thisResponse = "Sleep" then my deleteSwitchFile() my writetolog("System sent to sleep because user responded \"Sleep\" to shutdown dialog.") tell application "Finder" ignoring application responses sleep end ignoring return end tell end if if button returned of thisResponse = "No" then my deleteSwitchFile() my writetolog("System state unaltered because user responded \"No\" to shutdown dialog.") return end if end if my writetolog("Reached end of recordingDone script without altering the machine state. We shouldn't really have got here. Yikes.") my deleteSwitchFile() --display dialog "we are at the end of the recording done script" end RecordingDone --------------------------------------------------------------------------------------------------------------------------------------- on initLogFile() set fullLogFileName to ((path to documents folder as text) & "eyeTV-recordingDoneLog.txt") set posixLogFileName to POSIX path of fullLogFileName --check for existence of log file, if not existing then create it. tell application "Finder" if not (exists file fullLogFileName) then do shell script "touch " & quoted form of posixLogFileName my writetolog("This is the log file for eyeTV's recodingDone triggered script.") my writetolog("This file may be deleted at any time, recordingDone will create a new log as required.") end if end tell end initLogFile --------------------------------------------------------------------------------------------------------------------------------------- -- testing code: this will not be called when triggered from EyeTV, but only when the script is run as a stand-alone script on run tell application "EyeTV" set rec to unique ID of item 1 of every recording my RecordingDone(rec) end tell end run --------------------------------------------------------------------------------------------------------------------------------------- on writetolog(logLine) set logLine to (current date) & ": eyeTV recordingID: " & currentRecordingID & ": " & logLine set fullCommand to "echo \"" & logLine & "\" >> " & posixLogFileName do shell script fullCommand end writetolog --------------------------------------------------------------------------------------------------------------------------------------- on quitFirefox() writetolog("Firefox has been found to be running. An attempt will be made to quit it before shutting down.") tell application "Firefox" quit delay 2 * minutes end tell set firefoxrunning to false tell application "System Events" set firefoxrunning to (name of processes) contains "Firefox" end tell if firefoxrunning is true then my writetolog("After waiting 2 minutes, firefox is still running, so this script will wait a further 2 minutes.") tell application "Firefox" ignoring application responses quit end ignoring end tell delay 2 * minutes else my writetolog("Firefox has successfully quit.") return end if set firefoxrunning to false tell application "System Events" set firefoxrunning to (name of processes) contains "Firefox" end tell if firefoxrunning is true then my writetolog("After waiting a further 2 minutes, firefox is still running, so this script will now force it to close.") do shell script "killall firefox" --delay 5 * minutes end if end quitFirefox --------------------------------------------------------------------------------------------------------- to check_for_another_instance() --lets put back the random duration wait again my writetolog("Now checking for another running instance of this script.") set otherInstance to false set fullFileName to ((path to documents folder as text) & "eyetvswitch.txt") set posixFileName to POSIX path of fullFileName set otherInstance to false --display dialog fullFileName --do shell script "rm -f " & quoted form of posixFileName tell application "Finder" if exists file fullFileName then my writetolog("Switch file has been found to exist.") try set referenceNumber to open for access fullFileName with write permission on error errText number errNum if (errNum is not equal to 0) then my writetolog("An error has occurred whilst trying to open switch for access(1): " & errNum & return & errText) set otherInstance to true end if end try else my writetolog("Switch file has been found not to exist. it will be created and locked.") try set referenceNumber to open for access fullFileName with write permission on error errText number errNum if (errNum is not equal to 0) then my writetolog("An error has whilst trying to open switch for access(2): " & errNum & return & errText) set otherInstance to true end if end try end if if otherInstance = true then my writetolog("Another instance of this script is running, so this instance will exit without any further action.") return true else my writetolog("No other instance of this script is running, so it will continue and prevent others from running simultaneously.") return false end if return otherInstance end tell end check_for_another_instance --------------------------------------------------------------------------------------------------------------------------------------- on deleteSwitchFile() set errNum to 0 if otherInstance = false then try close access referenceNumber on error errText number errNum if (errNum is not equal to 0) then do shell script "rm -f " & quoted form of posixFileName my writetolog("An error has occurred whilst closing switch file: " & errNum & return & errText) end if end try if errNum = 0 then my writetolog("Switch file successfully closed.") end if do shell script "rm -f " & quoted form of posixFileName end if end deleteSwitchFile ---------------------------------------------------------------------------------------------------------------------------------------
The clock is ticking, all over again….
As I begin to write, 11 days, 15 hours, 40 minutes and 13 seconds is all that remains until the beginning of the first race weekend of the 2011 Formula 1 season. I’ve been observing F1 for most of my life, but 1989 was the year when my interest (and understanding) increased to the sort of level it still is now. It also marked the start of the post turbo era and the return to normally aspirated engines. It might also have marked the start of an era in F1 when a Sunday afternoon procession of increasingly expensive motors began. A procession lacking many of the attributes you’d look for in a race – not least that holy grail of overtaking.
For me, I feel much the same as I have at this point in the last 21 seasons: optimistic. Those who know me would rarely describe as an optimistic person. I have always been optimistic that the coming season would provide: more overtaking, no team absolutely dominating, more than two potential winning drivers, more than one potential championship winning team. In these regards, I have usually been disappointed. That is not to say that I have been more generally disappointed. I haven’t – there have been some great spectacles and extraordinary battles, just all too often with only two protagonists (Senna/Prost, Schumacher/Hill, Alonso/Schumacher, Schumacher/Hakinnen….). Every season, the technical battle and political strife provide a great deal of interest, without fail.
Without the degree of overtaking I would like, the next best thing to hope for is a season, where you cannot predict at the beginning who will triumph at the end; a season where there may be more than two different race winners. In all my time, it was 2003 that failed to disappoint. That is, of course until 2007.
What happened in 2007? (I hear you all say). The race, to the title that is, did not disappoint. It hasn’t disappointed since. There have been some processional races, but the last four seasons have provided interest right up to the wire – a bookie’s nightmare. The debate about what changed could rage and rage; the F1 rules are a work in progress and many factors change each year. The impact that any change will have on the racing is never easy to predict, and often is only understood with the help of much hindsight.
All I can offer is my own view. F1 has always had great drivers. In F1, just being a great driver is not enough. You need to be a great driver in the greatest car of the season (or as Schumacher proved, an exceptional driver in a good car). F1 has shown me that being a supreme driver in another formula is no guarantee of F1 greatness; similarly drivers with no previous conspicuous greatness find their place in F1. For the last four years we have had a large number of great drivers at one time. How have we ended up with so many great drivers at once? I think it is because of the previous rules which allowed for more testing and the use of the third driver at race weekends (for the less successful teams) that has delivered so many greats at once. It was in this try before you buy era (now sadly ended) that the likes of Kubica, Vettel and Hamilton, found their way into the money seats. 15 years before they may not have had the chance to be seen. But it isn’t just a surplus of good drivers that has made the difference.
As ever in F1 it is not just about the driver. In the post turbo era, all too often there has been a predominant car and one which may be able to clip at its heels given the right circumstances. This seems to have changed since 2007 and we now have a number of cars which could win any given race. There could be a number of reasons for this: the standard electronics package; the ban on engine development; season limits on the number of engines used; a clearly defined limit to testing; the apparent ability of teams to develop cars within a season. Often rule changes have little impact on the track but instead an impact on the car or how the team develops it.
All of this stands for the current season. But this year, I am slightly more optimistic than usual that we will see something other than a procession. For a start, we are going to have a different tyre supplier, providing tyres designed to degrade more rapidly than last year’s. We shall therefore return to the strategic decision making that went with refueling. We shall also see the return of KERS . We have seen KERS before, but this time it might be fitted to more of the field and may be more reliable. This time around it is combined with a moveable rear wing, which can be deployed, by the driver, at parts of the track, as determined by the stewards. Even the drivers seem unable to predict whether it will indeed result in more overtaking or not – I couldn’t possibly say, but I’m sure it will provide much interest, both on and off the pitch.
It seems to me, that in this limited testing world that the teams now find themselves, risks have to be taken with the design. It can already be seen from the pre-season testing that many teams have come up with radical ideas: McLaren with its interesting sidepods, Red Bull and Renault with new (and different) exhaust systems; And that is just to mention a couple – even the lesser teams are will be trying radical things. Just by looking at the cars, I can’t help feeling, that thus far there is no certain or prescribed way of building the fastest car for this season. We shall have to wait and see who has got it right. Few would doubt that the Red Bull and Ferrari will be fast cars, and that the McLaren and Mercedes will become fast cars. But this year there might just be one or two surprises from the mid field, or even the rear.
Bring it on, just 11 days, 12 hours, 49 minutes and 47 seconds to go.