#!/usr/bin/env python
"""
Camera action scheduler.
"""
__author__ = "Daniel Casner <www.danielcasner.org>"

import time
import scheduler
import control

SEEK_TIME = 10.0

class SnapshotAction:
    """An class to store the necessary information to execute 1 or more snapshots
    immediately or at a time in the future."""
    
    def __init__(self, foscam, preset, callback, number=1, interval=None, expire=None):
        """Setup the action closure.
        @param foscam driver object
        @param preset Preset to take snapshots at
        @param callback Function to call with image data
        @param number Count of snapshots to take
        @param interval If number > 1, interval between snapshots
        @param expire If time passes expire, delete the task
        """
        self.cam      = foscam
        self.preset   = preset
        self.callback = callbakc
        self.number   = number
        self.interval = interval
        self.expire   = expire
        self.lastTime = 0.0
        
    def run(self):
        """Run the snapshot action.
        @return True if this action is done and can be removed from the queue.
        False if the action has more to do."""
        if self.expire is not None and time.time() > self.expire:
            return False
        else:
            self.cam.goto_preset(self.preset)
            time.sleep(SEEK_TIME)
            remaining = self.interval - (time.time() - self.lastTime)
            if remaining > 0.0: time.sleep(remaining)
            while self.number > 0:
                self.lastTime = time.time()
                self.callback(self.cam.snapshot())
                self.number -= 1
                if self.interval <= SEEK_TIME:
                    time.sleep(self.interval)
                else:
                    return True
            return False


class FoscamScheduler(scheduler.Scheduler):
    "A scheduler specific for a given foscam"
    
    def __init__(self, foscam):
        scheduler.Scheduler.__init__(self)
        self.cam = foscam
    
    def snapshot(self, priority, preset, callback, expire=None):
        """Request a snapshot at a given preset.
        snapshots will go into the priority queue and execute when it is their
        turn. A snapshot will not be cancelled if another request with higher 
        priority arrives while it is being executed.
        @param priority honor system priority number for this request, larger numbers = higher priority.
        @param preset The preset to take the picture at.
        @param callback Function to call with the photo data
        @param expire Latest time that the caller wants the photo. None for no expiration.
        """
        self.append(priority, SnapshotAction(self.cam, preset, callback, expire=expire))
    
    def interval(self, priority, preset, callback, number, period, expire):
        """Requests a series of snapshots at a given present.
        @param priority honor system priority number for this request, larger numbers = higher priority.
        @param preset The preset to take the picture at.
        @param callback Function to call each successive frame.
        @param number How many pictures to take.
        @param period How many seconds between pictures.
        @param expire Latest time that the caller wants the photo. None for no expiration.
        """
        self.append(priority, SnapshotAction(self.cam, preset, callback, number, period, expire))
    

@@ -158,17 +158,17 @@
 _TIME = 
-1
+2
 0.0%0A%0Acla
@@ -971,35 +971,35 @@
 re%0A        self.
-las
+nex
 tTime = 0.0%0A    
@@ -1289,193 +1289,195 @@
   el
-se:%0A            self.cam.goto_preset(self.preset)%0A            time.sleep(SEEK_TIME)%0A            remaining = self.interval - (time.time() - self.lastTime)%0A            if remaining %3E 0.0:
+if time.time() %3C self.nextTime - SEEK_TIME: # Not ready to run yet, snooze to the scheduler%0A            return True%0A        else:%0A            self.cam.goto_preset(self.preset)%0A           
  tim
@@ -1488,17 +1488,17 @@
 eep(
-remaining
+SEEK_TIME
 )%0A  
@@ -1534,52 +1534,8 @@
  0:%0A
-                self.lastTime = time.time()%0A
     
@@ -1721,32 +1721,108 @@
           else:%0A
+                    self.nextTime = time.time() + self.interval - SEEK_TIME%0A
                 
@@ -2883,16 +2883,21 @@
 , expire
+=None
 ):%0A     

Make the cam scheduler for interval actions incrementally less stupid.