Sleeptimer - Gute Idee gesucht.

  • Hey,

    ich bastle mir gerade einen Sleeptimer für den DVB Viewer (gibts zwar schon einen - der ist aber "komisch" :rolleyes: )

    vorab mal mein Skript

    Spoiler anzeigen
    [autoit]


    Global $iCounter
    Global $dummy = 0
    If $CmdLine[0] = 0 Then Exit ;eigentlich unnötig - ich wollt lieber mit Parameter starten und naja wie gesagt ..

    [/autoit] [autoit][/autoit] [autoit]

    Global $DVBViewer = ObjGet("", "DVBViewerServer.DVBViewer") ;Verbindung zum DVBViewer herstellen
    If $DVBViewer = 0 Then
    MsgBox(1, "", "Keine Verbindung zum DVBViewer möglich")
    Exit
    EndIf
    If $CmdLine[0] > 0 And $CmdLine[1] = "-state" And $iCounter <> "" Then _STOPTimer() ;daran hängts irgendwie :(

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Switch $dummy
    Case 0
    $test = $DVBViewer.OSD.showpopup("Sleeptimer", "30min, 60min, 90min, 120min, 180min, Zurück", True) ;OSD um abzufragen wie lange der Sleeptimer laufen soll
    Switch $test
    Case 0
    $iCounter = 30 ;30sek zum testen
    _Timer()
    Case 1
    $iCounter = 60 ;60sek usw.
    _Timer()
    Case 2
    $iCounter = 90
    _Timer()
    Case 3
    $iCounter = 120
    _Timer()
    Case 4
    $iCounter = 180
    _Timer()
    Case 5
    $DVBViewer.SendCommand(82) ;osd zurück
    Exit
    EndSwitch
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _STOPTimer()
    $test = $DVBViewer.OSD.showyesno("Sleeptimer", "Restlaufzeit:" & $iCounter, "Countdown abbrechen?", "", True) ;OSD Fenster mit der verbleibenden Zeit wird und einer Abfrage wird angezeigt
    Switch $test
    Case True
    Exit ;Countdown abbrechen
    Case False
    $dummy = 1 ;blöder Versuch von mir das Problem zu lösen bei $dummy = 1 soll er eben nicht das Auswahlfenster zeigen.
    EndSwitch
    EndFunc ;==>_STOPTimer

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _Timer() ; Die Timerfunktion
    AdlibEnable('_Countdown', 1000)
    While True
    If $iCounter <= 0 Then
    AdlibDisable()
    _Beenden()
    Exit
    EndIf
    WEnd
    EndFunc ;==>_Timer

    [/autoit] [autoit][/autoit] [autoit]

    Func _Countdown()
    $iCounter -= 1
    EndFunc ;==>_Countdown

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _Beenden() ; kommt noch - tut auch nichts zur Sache

    EndFunc ;==>_Beenden

    [/autoit]

    Das Skirpt wird vom DVBViewer aus gestartet, danach fängt der Timer mit der ausgewählten Zeit an zu laufen.
    Jetzt kommt der knifflige Teil. Ich möchte das Skript erneut aufrufen (mit dem gleichen Parameter) und nun abfragen wie lange der Timer noch läuft und ob er abgebrochen werden soll.

    Es gelingt mir aber nicht in die entsprechende Funktion zu kommen. D.h. es wird erneut abgefragt mit wieviel Zeiteinheiten der Timer anlaufen soll, obwohl er ja schon läuft.

    Jemand dazu eine gute Idee?

    Gruß nuts

    Edit \ Mit _Singleton würde da was gehen :D nur dann läuft das Skript 2 mal -> wie kille ich ggf. beide Instanzen auf einmal? ;(
    _Singleton Version - wenn ich noch raus kriege wie man die beiden gleichzeitig beenden kann hab ichs!

    Spoiler anzeigen
    [autoit]


    #include <Misc.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $iCounter
    If $CmdLine[0] = 0 Then Exit ;eigentlich unnötig - ich wollt lieber mit Parameter starten und naja wie gesagt ..

    [/autoit] [autoit][/autoit] [autoit]

    Global $DVBViewer = ObjGet("", "DVBViewerServer.DVBViewer") ;Verbindung zum DVBViewer herstellen
    If $DVBViewer = 0 Then
    MsgBox(1, "", "Keine Verbindung zum DVBViewer möglich")
    Exit
    EndIf
    Global $sTitle = 'Sleeptimer'
    If _Singleton($sTitle, 1) = 0 Then _STOPTimer()

    [/autoit] [autoit][/autoit] [autoit]

    $test = $DVBViewer.OSD.showpopup("Sleeptimer", "30min, 60min, 90min, 120min, 180min, Zurück", True) ;OSD um abzufragen wie lange der Sleeptimer laufen soll
    Switch $test
    Case 0
    $iCounter = 30
    _Timer()
    Case 1
    $iCounter = 60
    _Timer()
    Case 2
    $iCounter = 90
    _Timer()
    Case 3
    $iCounter = 120
    _Timer()
    Case 4
    $iCounter = 180
    _Timer()
    Case 5
    $DVBViewer.SendCommand(82) ;osd zurück
    Exit
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _STOPTimer()
    $test = $DVBViewer.OSD.showyesno("Sleeptimer", "Restlaufzeit:" & $iCounter, "Countdown abbrechen?", "", True) ;OSD Fenster mit der verbleibenden Zeit wird und einer Abfrage wird angezeigt
    Switch $test
    Case True
    Exit
    EndSwitch
    EndFunc ;==>_STOPTimer

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _Timer() ; Die Timerfunktion
    AdlibEnable('_Countdown', 1000)
    While True
    If $iCounter <= 0 Then
    AdlibDisable()
    _Beenden()
    Exit
    EndIf
    WEnd
    EndFunc ;==>_Timer

    [/autoit] [autoit][/autoit] [autoit]

    Func _Countdown()
    $iCounter -= 1
    EndFunc ;==>_Countdown

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _Beenden() ; kommt noch - tut auch nichts zur Sache

    [/autoit] [autoit][/autoit] [autoit]

    EndFunc ;==>_Beenden

    [/autoit]

    edit2 \
    So hab gerade gemerkt, dass meine eingeschlagenen Lösungswege ziemlich ins leere laufen :S
    Das Skript 2 mal starten geht nicht, da sonst keine Restlaufzeit angezeigt werden kann.
    Die Abfrage ob abgebrochen werden soll muss irgendwie anders aufgerufen werden -> Ich versuchs jetzt mal mit _ISPressed :rolleyes:

    Hab ich das Problem halbwegs klar dargestellt?
    Der Sleeptimer soll per Fernbedienung gestartet werden und zwar mit nur einem Knopf. Dieser Knopf kann logischerweise nur eine Aktion aufrufen.
    Gewünscht ist eine unterscheidung zwischen "läuft schon -> Abfrage ob abgebrochen werden soll und die Anzeige der Restlaufzeit" und "läuft nicht -> Einstellen des Countdowns und los gehts".

    Schwierig schwierig ..

    6 Mal editiert, zuletzt von nuts (15. Mai 2009 um 23:48)

  • Hey,

    deine Antwort habe ich gar nicht gesehen :(


    Wollte das Problem nochmal aufgreifen, da ich es leider immernoch nicht zufriedenstellend gelöst habe.

    Im Prinzip lässt sich die Aufgabenstellung darauf reduzieren, dass ein gestartetes Skript über einen Kommandoparameter Befehle annimmt.

    Beispiel:
    test.exe -e startet den Countdown und setzt ein flag gestartet;
    wird test.exe -e erneut gestartet soll nicht das ganze Programm neugestartet werden, sondern das laufende Programm eine Funktion aufrufen (entsprechendes flag kann man davor überprüfen).

    Beispielprogramme die einen Funktionsaufruf über Kommandoparamter erlauben: DVBViewer, Eventghost (mehr fallen mir grad nicht ein :D)

    edit\ wenn es unklar ist was ich meine - bitte melden ;)

  • Scheint wohl nicht zu gehen?

    Ist es möglich, dass 2 (gleiche) Skripte mit einander kommunizieren? Die zuletzt gestartete Instanz könnte sich dann den Countdownstand vom der ersten holen, diesen Anzeigen und sich wieder beenden.

    • Offizieller Beitrag

    Hier mal sehr vereinfacht

    Spoiler anzeigen
    [autoit]


    If $cmdline[0] = 0 Then
    switcher(1)
    ElseIf $cmdline[0] = 1 Then
    switcher($cmdline[1])
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    Func Switcher($nr)
    Switch $nr
    Case 1
    _1()
    _2()
    _3()
    Case 2
    _2()
    _3()
    Case 3
    _3()
    EndSwitch
    EndFunc ;==>Switcher

    [/autoit] [autoit][/autoit] [autoit]

    Func _1()
    ConsoleWrite(1 & @CRLF)
    EndFunc ;==>_1

    [/autoit] [autoit][/autoit] [autoit]

    Func _2()
    ConsoleWrite(2 & @CRLF)
    EndFunc ;==>_2

    [/autoit] [autoit][/autoit] [autoit]

    Func _3()
    ConsoleWrite(3 & @CRLF)
    EndFunc ;==>_3

    [/autoit]

    Mega

  • Danke für dein Bemühen, ich glaube wir haben uns doch missverstanden.

    Es soll keine 2. Instanz gestartet werden, sondern durch ein eneutes Aufrufen soll der 1. Instanz etwas mitgeteilt werden (Rufe Funktion XY auf oder sowas).

    Meine einzige Idee wäre über einen zweiten Mutex ?(

  • Danke für dein Bemühen, ich glaube wir haben uns doch missverstanden.

    Es soll keine 2. Instanz gestartet werden, sondern durch ein eneutes Aufrufen soll der 1. Instanz etwas mitgeteilt werden (Rufe Funktion XY auf oder sowas).

    Meine einzige Idee wäre über einen zweiten Mutex ?(

    mutex verfahren kannst du bei autoit vergessen da es nicht mutlithreading fähig ist

  • naja nicht wirklich, da ja das hauptscript pausiert wird...

    ist auch wurst, hat mit dem thread ja nix zu tun

  • So, hier ist ein Beispiel, wie die Kommandozeilenparameter an das erste Skript übergeben werden können ;) (Habe dazu das etwas verändert)

    Spoiler anzeigen
    [autoit]

    #Include <Array.au3>
    #Include <GUIConstantsEx.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt('WinTitleMatchMode', 3)

    [/autoit] [autoit][/autoit] [autoit]

    global const $TITLE_RECEIVER = 'DVBViewerSleepTimerReceiver'
    global const $WM_COPYDATA = 0x004A
    Global $NewDataAvailable = False, $avData[1]

    [/autoit] [autoit][/autoit] [autoit]

    if WinExists($TITLE_RECEIVER) then
    ; Kommandozeile an schon laufendes Skript weitergeben
    If $CMDLINE[0] = 0 Then Exit
    _SendData(WinGetHandle($TITLE_RECEIVER),$CMDLINERAW)
    Exit
    else
    ; Empfänger mit normalem Skript starten
    _Receiver()
    Exit
    endif

    [/autoit] [autoit][/autoit] [autoit]

    func _Receiver()
    GUICreate($TITLE_RECEIVER)
    GUIRegisterMsg($WM_COPYDATA, '_WM_COPYDATA')

    [/autoit] [autoit][/autoit] [autoit]

    while 1
    Sleep(10)
    if $NewDataAvailable then
    $NewDataAvailable = False
    $sMsg = $avData[1]
    _ArrayDelete($avData,1)
    $aMsg = _ParseCMDLine($sMsg)
    For $i = 0 To UBound($aMsg)-1
    Switch $aMsg[$i][1]
    Case "dauer"
    MsgBox(0, '', "Dauer anzeigen")
    Case "stop"
    MsgBox(0, '', "beenden")
    Exit
    EndSwitch
    Next
    endif
    wend

    [/autoit] [autoit][/autoit] [autoit]

    GUIDelete()
    endfunc; _Receiver

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ;
    ; Function Name: _ParseCMDLine($CMDString)
    ; Description:: Parses a CMD-String to Parameters with Values
    ; Parameter(s): $CMDString -> String to parse
    ; Requirement(s): ?
    ; Return Value(s): Error: 0 and @error = StringRegExp-Error
    ; Success: 2 Dimensional Array:
    ; $array[$i][0] : Parameter including value
    ; $array[$i][1] : Parameter
    ; $array[$i][2] : Value with quotation marks (only if value has quotaion marks)
    ; $array[$i][3] : Value without quotation marks
    ; Author(s): Prog@ndy
    ;
    ; Basis: http://regexlib.com/REDetails.aspx?regexp_id=1220
    ;===============================================================================
    ;
    Func _ParseCMDLine($CMDString)
    Local $y, $j, $i, $entry
    Local $x = StringRegExp($CMDString,'(?:\s*)(?<=[-|/])(?<name>[^\s-|/:|=]*)(?:(?:[:|=](?:("(?<value1>.*?)(?<!\\)")|(?<value>\S*)))|\w*?)',4)
    If @error Then Return SetError(@error,0,0)
    Local $ResultArray[UBound($x)][4]
    For $i = 0 To UBound($x)-1
    $entry = $x[$i]
    For $y = 0 To UBound($entry)-1
    $j = $y
    If $y > 3 Then $j = 3
    $ResultArray[$i][$j] = $entry[$y]
    Next
    Next
    Return $ResultArray
    EndFunc
    func _SendData($hWnd, $sData)

    [/autoit] [autoit][/autoit] [autoit]

    local $tCOPYDATA, $tMsg

    [/autoit] [autoit][/autoit] [autoit]

    $tMsg = DllStructCreate('wchar[' & StringLen($sData) + 1 & ']')
    DllStructSetData($tMsg, 1, $sData)
    $tCOPYDATA = DllStructCreate('dword;dword;ptr')
    DllStructSetData($tCOPYDATA, 2, DllStructGetSize($tMsg))
    DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tMsg))
    $Ret = DllCall('user32.dll', 'lparam', 'SendMessageW', 'hwnd', $hWnd, 'int', $WM_COPYDATA, 'wparam', 0, 'lparam', DllStructGetPtr($tCOPYDATA))
    if (@error) or ($Ret[0] = -1) then
    return 0
    endif
    return 1
    endfunc; _SendData

    [/autoit] [autoit][/autoit] [autoit]

    func _WM_COPYDATA($hWnd, $msgID, $wParam, $lParam)

    [/autoit] [autoit][/autoit] [autoit]

    local $tCOPYDATA = DllStructCreate('dword;dword;ptr', $lParam)
    local $tMsg = DllStructCreate('wchar[' & DllStructGetData($tCOPYDATA, 2)/2 & ']', DllStructGetData($tCOPYDATA, 3))

    [/autoit] [autoit][/autoit] [autoit]

    _ArrayAdd($avData, DllStructGetData($tMsg, 1))
    $NewDataAvailable = True

    [/autoit] [autoit][/autoit] [autoit]

    return 0
    endfunc; _WM_COPYDATA

    [/autoit]
  • hey,

    danke für die zahlreichen Vorschläge.

    Auslagern (.txt, .ini oder sonstwas) ist zumindest beim Übergeben eines Timers nicht wirklich optimal.

    Über einen zweiten Mutex geht wohl auch nicht.

    Bleibt die Variante von progandy - die schau ich mir morgen genau an.

  • Ja klar, die Geschwindigkeit leidet darunter, aber schneller gehts auch nicht.

    Wie ist es denn, wenn dein Programm eine versteckte GUI öffnet, in die das andere in ein Input reinschreibt (Control-Funktionen), die das Programm entgegennimmt? :)