Hi everybody (mostly Dischi, Rob)! Some time ago I promised to "finish" the nvram-wakeup integration. Currently, I am still running the 1.5 branch with the old (again attached), only slightly improved patch. The following problems still exist / features I wanna do (I will go into detail later): - Freevo should shutdown after the recording. - One might need to reboot the machine to make changes take effect. - One must use the freevo shutdown option to start the programming.
What the patch does, is adding some user feedback, if he/she selects "Shutdown" during/before a recording. This will also be useful without nvram-wakeup. Shutdown after recording: ------------------------ I had a look at freevoscreensaver.py (BTW: why isn't it just screensaver.py?), which gave me enough insight to write something similar for the automatic shutdown. Some thoughts: - One cannot be sure that the computer was powered up because of a previous nvram-wakeup programming. I planned to check on Freevo startup whether the computer boot-up happend in a sane range (depending on config settings) before the next recording, assuming that it's the programmed start. - Furthermore, I wanna check for any events (similar to the screensaver) which tell me that a human has started playing with Freevo, and cancel that automatic shutdown. - Else, I want to display a "waiting for recording to finish" message with a "cancel" button (possibly even telling the remaining number of minutes), which can also be activated manually: If the user presses "Shutdown" during the recording, he/she will get this dialog with "Cancel" and "Force Shutdown" buttons. QUESTION: I digged into plugin.py, wondering about the implementation of Plugin and the subclasses. Am I right that it's not possible to have ONE plugin that has both menu items and a poll function? What's the expected way to do sth. like that? Necessary Reboots: ----------------- If nvram-wakeup is called to program an automatic startup, it may return an exitcode of 1 (which it does on my system), which means that the computer needs to be restarted, because the BIOS has to finish the programming. In this case, my patch currently creates a flag file (of configurable location), and I added a "rebootflag" helper which checks this flag and by default calls config.SHUTDOWN_SYS_CMD: freevo rebootflag [-c|-d|-s] [-v] -c only CHECK for the flag, exitcode 0 if present, 1 otherwise -d check for flag (as -c), and DELETE afterwards if it existed -s like -d but also SHUTDOWN the system if the flag existed (default) -v be verbose This way, "freevo rebootflag" can be integrated into the early boot sequence to shut the system down ASAP. There are two possible additions: 1. One could change grub.conf (or similar) on shutdown if "freevo rebootflag -d" returns 0, to further reduce the bootup time for this extra run. I think this can safely be left to the advanced Freevo user. 2. I think a useful addition would be to check the flag also on Freevo startup, in case that the user did not yet integrate "freevo rebootflag" into his/her boot sequence. This leads me to this other simple QUESTION: How can I re-use code between plugins and helpers? (E.g. call a function from helpers/rebootflag.py from plugins/shutdown.py or vice versa, to prevent code duplication.) Is there a special Freevo-way? Shutdown via Freevo: ------------------- Something that struck me lately is that after being logged into my Freevo maching remotely and maintaining the Gentoo system, I issued "halt"... which was stupid because the next two recordings on the following days were not executed because the nvram-wakup call happens in shutdown.py. :-( I have two options in my mind: - Let the recordserver to the nvram-wakup programming. This would ensure that recordings will happen, as long as no reboot is needed. The rebootflag would have to be checked on Freevo _or_ system shutdown however - one could add another "freevo halt" helper, and/or check the rebootflag on system shutdown; does so. know whether it's possible to change a shutdown in progress from runlevel 0 to 6/reboot? - Force the user to shutdown the machine through Freevo (probably the above-mentioned helper would be no bad idea, then). QUESTION: Which option is better/preferred? Looking at my code, there's much room for improvement, and I'd like to cleanup shutdown.py in some more respects, paving the way for better suspend-integration, too. I would be glad if you could answer my Freevo-architecture-related questions; also I'd be interested how much of this code can be re-used (/has to be redone) for Freevo 2? Ciao, / / .o. /--/ ..o / / ANS ooo
Index: local_conf.py.example =================================================================== RCS file: /cvsroot/freevo/freevo/local_conf.py.example,v retrieving revision 1.37.2.2 diff -u -3 -p -d -b -r1.37.2.2 local_conf.py.example --- local_conf.py.example 21 Oct 2004 13:54:31 -0000 1.37.2.2 +++ local_conf.py.example 14 Nov 2004 22:08:36 -0000 @@ -771,12 +771,25 @@ IMAGEVIEWER_BLEND_MODE = -1 # TV_RECORD_SERVER_IP = 'localhost' # TV_RECORD_SERVER_PORT = 18001 -# start every recording X minutes before scheduled, +# Start every recording X minutes before scheduled, # and stop X minutes after scheduled - default to zero minutes. # This must be a value in seconds although at the moment only has # the percision of one minute. # TV_RECORD_PADDING = 0 * 60 +# Warn before shutting down the system if the next recording is +# scheduled for starting in less than this number of seconds: +# WARN_SHUTDOWN = 15 * 60 # quarter hour +# (This has no extra effect if CONFIRM_SHUTDOWN is set, since then +# the shutdown is already confirmed.) + +# On Freevo shutdown, use nvram-wakeup to program the computer to +# wakeup / boot up right before the next recording: +# USE_NVRAM_WAKEUP = 1 + +# If using nvram-wakeup, time in seconds to startup before recording: +# BOOTTIME_PADDING = 2 * 60 + # VCR_AUDIO = (':adevice=%s' % AUDIO_DEVICE + # ':audiorate=32000' + # 44100 for better sound # ':forceaudio:forcechan=1:' + # Forced mono for bug in my driver Index: freevo_config.py =================================================================== RCS file: /cvsroot/freevo/freevo/freevo_config.py,v retrieving revision 1.349.2.4 diff -u -3 -p -d -b -r1.349.2.4 freevo_config.py --- freevo_config.py 1 Nov 2004 21:38:58 -0000 1.349.2.4 +++ freevo_config.py 14 Nov 2004 22:08:37 -0000 @@ -293,6 +293,24 @@ RESTART_SYS_CMD = 'shutdown -r now' # ENABLE_SHUTDOWN_SYS = 0 # Performs a whole system shutdown at SHUTDOWN! # For standalone boxes. +# Warn before shutting down the system if the next recording is +# scheduled for starting in less than this number of seconds: +WARN_SHUTDOWN = 15 * 60 + +# On Freevo shutdown, use nvram-wakeup to program the computer to +# wakeup / boot up right before the next recording: +USE_NVRAM_WAKEUP = 0 + +# See SHUTDOWN_SYS_CMD for sudo comment. +# If you change this, note that an exitcode of 1 means "reboot needed" +# and should get through to Freevo +NVRAM_WAKEUP_CMD = 'nvram-wakeup -s %d' + +# If using nvram-wakeup, time in seconds to startup before recording: +BOOTTIME_PADDING = 150 + +# Location of the reboot-flag used if nvram-wakeup returns 1: +NVRAM_REBOOT_FLAG = '%s/reboot_flag' % FREEVO_CACHEDIR # # You can add more keybindings by adding them to the correct hash. Index: src/plugins/shutdown.py =================================================================== RCS file: /cvsroot/freevo/freevo/src/plugins/shutdown.py,v retrieving revision 1.7 diff -u -3 -p -d -b -r1.7 shutdown.py --- src/plugins/shutdown.py 10 Jul 2004 12:33:40 -0000 1.7 +++ src/plugins/shutdown.py 14 Nov 2004 22:08:37 -0000 @@ -50,6 +50,9 @@ from gui import ConfirmBox from item import Item from plugin import MainMenuPlugin +if config.WARN_SHUTDOWN or config.USE_NVRAM_WAKEUP: + import tv.record_client as record_client + def shutdown(menuw=None, argshutdown=None, argrestart=None, exit=False): """ @@ -126,7 +129,6 @@ def shutdown(menuw=None, argshutdown=Non time.sleep(1) - class ShutdownItem(Item): """ Item for shutdown @@ -146,7 +148,7 @@ class ShutdownItem(Item): (self.confirm_system_restart, _('Restart system') ) ] else: items = [ (self.shutdown_freevo, _('Shutdown Freevo') ), - (self.shutdown_system, _('Shutdown system') ), + (self.check_shutdown_system, _('Shutdown system') ), (self.shutdown_system_restart, _('Restart system') ) ] if config.ENABLE_SHUTDOWN_SYS: items = [ items[1], items[0], items[2] ] @@ -154,12 +156,46 @@ class ShutdownItem(Item): return items + def next_scheduled_recording(self): + """ + return starting time of next scheduled recording (or None) + """ + (server_available, msg) = record_client.connectionTest() + if not server_available: + return None + (result, recordings) = record_client.getScheduledRecordings() + if result: + progs = recordings.getProgramList().values() + if len(progs): + progs.sort(lambda a, b: cmp(a.start, b.start)) + return progs[0].start + return None + + + def next_recording_message(self, format, start_time = None): + if start_time == None: + start_time = self.next_scheduled_recording() + if start_time == None: + return "" + rec_distance = start_time - time.time() - config.TV_RECORD_PADDING + if rec_distance < 0: + result = _('A recording is in progress.') + elif rec_distance < 60*60: + result = _('The next scheduled recording begins in %d minutes.') % int(rec_distance/60) + elif rec_distance < 60*60*10: + result = _('The next scheduled recording begins at %s.') % time.strftime(config.TV_TIMEFORMAT, time.localtime(start_time)) + else: + result = _('The next recording is scheduled for %s.') % time.strftime(config.TV_DATETIMEFORMAT, time.localtime(start_time)) + return format % result + + def confirm_freevo(self, arg=None, menuw=None): """ Pops up a ConfirmBox. """ self.menuw = menuw - what = _('Do you really want to shut down Freevo?') + what = _('Do you really want to shut down Freevo?') \ + + self.next_recording_message(" %s") ConfirmBox(text=what, handler=self.shutdown_freevo, default_choice=1).show() @@ -168,41 +204,87 @@ class ShutdownItem(Item): Pops up a ConfirmBox. """ self.menuw = menuw - what = _('Do you really want to shut down the system?') + what = _('Do you really want to shut down the system?') \ + + self.next_recording_message(" %s") ConfirmBox(text=what, handler=self.shutdown_system, default_choice=1).show() + def confirm_system_restart(self, arg=None, menuw=None): """ Pops up a ConfirmBox. """ self.menuw = menuw - what = _('Do you really want to restart the system?') + what = _('Do you really want to restart the system?') \ + + self.next_recording_message(" %s") ConfirmBox(text=what, handler=self.shutdown_system_restart, default_choice=1).show() + def check_shutdown_system(self, arg=None, menuw=None): + """ + Shutdown the complete system if the next recording is not too far away + """ + if config.WARN_SHUTDOWN: + start_time = self.next_scheduled_recording() + if start_time != None: + if start_time - config.TV_RECORD_PADDING - time.time() \ + < config.WARN_SHUTDOWN: + what = self.next_recording_message("%s ", start_time) + \ + _('Do you really want to shut down the system?') + ConfirmBox(text=what, handler=self.shutdown_system, default_choice=1).show() + return + self.shutdown_system(arg, menuw) + + def shutdown_freevo(self, arg=None, menuw=None): """ - shutdown freevo, don't shutdown the system + Shutdown freevo, don't shutdown the system """ shutdown(menuw=menuw, argshutdown=False, argrestart=False) def shutdown_system(self, arg=None, menuw=None): """ - shutdown the complete system + Shutdown the complete system, use nvram-wakeup to schedule + boot-up before next recording (if configured to do so). + nvram-wakup may signal that an additional reboot is needed + (with exitcode 1), in this case a flag file is created and the + system is rebooted. + """ + doShutdown = True + if config.USE_NVRAM_WAKEUP: + start_time = self.next_scheduled_recording() + if start_time != None: + wakeupTime = start_time \ + - config.TV_RECORD_PADDING \ + - config.BOOTTIME_PADDING + _debug_("calling nvram-wakeup with %d" % wakeupTime) + ec = os.system(config.NVRAM_WAKEUP_CMD % (wakeupTime,)) + _debug_(".. exitcode was %d" % ec) + if ec == 256: + doShutdown = False + file(config.NVRAM_REBOOT_FLAG, "w").close() + elif ec > 0: + ConfirmBox(text=_('Could not program computer to boot up before next recording. Shutdown anyway?'), + handler=self.shutdown_system_anyway, default_choice=1).show() + return + shutdown(menuw=menuw, argshutdown=doShutdown, argrestart=not doShutdown) + + + def shutdown_system_anyway(self, arg=None, menuw=None): + """ + Shutdown freevo, don't shutdown the system """ shutdown(menuw=menuw, argshutdown=True, argrestart=False) + def shutdown_system_restart(self, arg=None, menuw=None): """ - restart the complete system + Restart the complete system """ shutdown(menuw=menuw, argshutdown=False, argrestart=True) - - # # the plugins defined here # @@ -214,5 +296,3 @@ class PluginInterface(MainMenuPlugin): def items(self, parent): return [ ShutdownItem(parent) ] - -
rebootflag.py
Description: helpers/rebootflag.py