Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Zwei unabhängige Zeitschleifen D7 (https://www.delphipraxis.net/181591-zwei-unabhaengige-zeitschleifen-d7.html)

beanbear6 27. Aug 2014 12:40

Zwei unabhängige Zeitschleifen D7
 
Hallo Profis,
ich hab ein ganz spezielles Problem: eine Listbox1 wird im 250ms Takt abgearbeitet. Wird in dieser Box ein bestimmter Eintrag gefunden, wird eine weitere Zeitschleife mit Befehlen gestartet - dauert verschieden lang, z.B. 1 bis 5 Sekunden. Während dieser Zeit aber steht die erste Schleife der Listbox1.
Wie könnte man das machen, dass diese beiden Schleifen unabhängig laufen? Der Sinn der Sache ist folgender:
In der ersten Schleife gebe ich Licht(DMX) Daten an Scheinwerfer raus. Ist nun in der ersten Schleife ein Fade von z.B. 3 Sekunden eingestellt, so wird über ein Delay (Schleife2) der Scheinwerfer gedimmt. Und genau während dieser Zeit schläft sozusagen die erste Schleife und damit bin ich dann nicht mehr synchron mit der (dazu) laufenden Musik.
Das Ganze ist etwas schwierig zu erklären ich hoffe man kanns einigermaßen verstehen. Bin für jeden Tip mega Dankbar...
Gruß beanbear

jaenicke 27. Aug 2014 12:59

AW: Zwei unabhängige Zeitschleifen D7
 
Dafür kannst du den Inhalt deiner Listbox an einen Thread übergeben und das ganze asynchron von diesem regeln lassen. Dieser steuert dann wiederum weitere Threads, in denen die weiteren Steueraufgaben ausgeführt werden.

Die Alternative wäre, dass du die Abarbeitung nicht direkt hintereinander machst, sondern die Aktionen stückchenweise abarbeitest, dabei aber immer alle durchgehst. Sprich du schreibst alle abzuarbeitenden Aktionen in eine Liste und gehst dann immer die Liste durch und sagst jedem Eintrag, dass er einen Schritt weiter machen soll. Sind alle Schritte ausgeführt, wird der Eintrag aus der Liste entfernt.

Sir Rufo 27. Aug 2014 13:05

AW: Zwei unabhängige Zeitschleifen D7
 
Ähm "den Inhalt der Listbox an einen ... übergeben" halte ich nun nicht wirklich für klug gewählt.

Die Listbox kann anzeigen was sie möchte oder was sie soll, aber eben anzeigen.
Die Steuerung hat die auszuführenden Teile in einer Liste/Queue und arbeitet diese von da ab. Der Inhalt kann natürlich auch in einer Listbox visualisiert werden.

beanbear6 27. Aug 2014 13:54

AW: Zwei unabhängige Zeitschleifen D7
 
Hi,
ich hab keinen Ansatz, wie ich das machen soll... Hilfts etwa, wenn i bissl Quellcode poste? Und wie kann ich eine andere Schleife asynchron laufen lassen? Habts da no paar tips? Danke Euch für Eure Postings
Gruß beanbear

Sir Rufo 27. Aug 2014 14:06

AW: Zwei unabhängige Zeitschleifen D7
 
Du darfst diese "Zeitschleifen" nicht im Hauptthread laufen lassen, sondern jede in ihrem eigenen Thread. Der Hauptthread ist hauptsächlich zur Kommunikation mit dem Benutzer gedacht.

divBy0 27. Aug 2014 14:47

AW: Zwei unabhängige Zeitschleifen D7
 
Ich denke dein Ansazt ist verkehrt. Bei meiner DMX-Software habe ich einen Thread, der für das DMX-Universum zuständig ist (Ausgabe, Aktualisierung, Eingabe, usw.), dem Universum wird einfach ein DMX-Wert und die Fadetime übergeben.

Medium 27. Aug 2014 14:52

AW: Zwei unabhängige Zeitschleifen D7
 
Mit einem Standard-Timer wird man wohl zwangsweise immer irgendwan etwas der Musik hinter her oder vorweg laufen, selbst wenn man es "richtig" macht. Die Ungenauigkeiten addieren sich nach einiger Laufzeit sicherlich bemerkbar auf. Es wäre daher allein aus diesem Grund schon mal sinnig, einen Multimedia-Timer (viele Themen zu hier in der DP) zu nutzen.

Was die anderen aber auch schon sagten: Verabschiede dich am besten so früh wie möglich davon mehrere Timer zu benutzen. Baue dir eine Klasse, mit der du die nötigen Aktionen abbilden kannst, und nutze diese als Elemente einer Liste. Diese befüllst du anhand dessen, was in deinem DMX-Ablauf vorgeschrieben ist, und arbeitest sie dann durch. Aktionen die parallel stattfinden werden auch im selben Timer-Tick mit verarbeitet, dadurch ist u.a. auch sicher gestellt, dass die Abläufe synchron zu sich selbst sind.

Was du jetzt hast, klingt nach einer Timer-Schlacht mit mächtig Ausart-Potenzial und ggf. wackeligem Resultat. Nutze einen Taktgeber für alle, und viele Probleme lösen sich schon mal fast von selbst.

beanbear6 27. Aug 2014 15:56

AW: Zwei unabhängige Zeitschleifen D7
 
Hallo zusammen,
also ich hab nicht mehrere Timer, sondern nur einen... die zweite
Zeitschleife mach ich über Delay. Und genau um diese Zeit hängt
der Timer. Hier mal Codeschnippsl...

Delphi-Quellcode:
procedure TMain.StrListTimerTimer(Sender: TObject);
var i,k : Integer;
begin
  L.LoadFromFile('SC11_ROT ROT 100 F1.dat'); // hier ist ein Fade von 1 Sekunde eingetragen

  for i:=0 to 479 do begin // hier gebe ich die DMX Daten (Kanäle raus)
    dmxalt[i]:= dmxout[i];
    dmxneu[i]:=StrToInt(L.Strings[i]);
  end;

  // HIER BEGINNT DAS PROBLEM....
  // Um diese Delaytime verschiebt sich die Zeit
  // Wie krieg ich dieses Delay unabhängig ??
  for K:=0 to 100 do begin
    Delay(Trunc(StrToInt(l[481])/100));
    for I:=0 to 479 do     //nach       von
      DMXOut[I]:= Trunc((dmxneu[I] * K + dmxalt[I] * (100-K))/100);
  end;

  If Zahl < DMXList.Count-1 then begin
    Inc(Zahl);
    StrListTimer.Interval := StrToInt(Copy(DMXList[Zahl],1,Pos(',',DMXList[Zahl])-1))-StrToInt(L[481]); // Hier hol ich die neue Zeit für die nächste DMX-Scene
  end else begin
    StrListTimer.Enabled:= False;
    l.Free;
  end;
Hat bitte jemand irgendwie paar Zeilen die mir helfen könnten? Ich hab keinen Ansatz, wie ich das angehen soll... Bin echt dankbar für jede Hilfe...
Gruß beanbear

Union 27. Aug 2014 16:00

AW: Zwei unabhängige Zeitschleifen D7
 
Wenn Du bei dieser Lösung bleiben willst, dann ziehe doch das Delay vom zu setzenden Timer-Intervall ab.

beanbear6 27. Aug 2014 16:04

AW: Zwei unabhängige Zeitschleifen D7
 
Hi,
das geht nicht weil es kann sein, dass das delay länger ist als das Timerinterval und dann krieg ich ne negative zeit. Wenn ich ne andere Lösung wüsste, würd ichs machen. Aber bitte nicht böse sein es ist auch nicht böse gemeint, aber die bisherigen Antworten kann ich nicht umsetzen ich weis nicht wie das alles gemeint ist... bin nicht der guru in Delphi :oops::oops:
Kann mir bitte jemand bissl Code mit kurzer Erklärung posten damit ich nen Ansatz hab und das auch verstehen kann?
Gruß beanbear

Medium 27. Aug 2014 18:38

AW: Zwei unabhängige Zeitschleifen D7
 
Liste der Anhänge anzeigen (Anzahl: 1)
Stelle dir unsere Vorschläge etwa so vor:
(Jede Zeile stellt ein OnTimer-Event dar, sagen wir mal 250ms pro Zeile.)
Code:
DMX-Szenenanweisung Kanal1 Kanal2 Kanal3 ... Kanal479
-                      250     0
-                      250     0
-                      250     0
-                      250     0
Fade to 90 Ch1 2sec   230     0
-                      210     0
Fade to 100 Ch2 1sec  190    25
-                      170    50
-                      150    75
-                      130   100
-                      110   100
-                       90   100
-                       90   100
-                       90   100
Die DMX-Szenenanweisungen sind das, was du bereits hast. Diese sorgen dafür, dass in die Liste für den betreffenden Kanal ab Auftreten die nächsten N Zwischenwerte geschrieben werden. Dies passiert bei jedem Timer-Tick, je für eine Zeiteinheit weiter als vorher, aber eine Anweisung schreibt alle daraus resultierenden zukünftigen Werte bereits in einem Rutsch vorab in ihren Kanal. Nachdem die Szenenanweisungen fertig sind, gibst du nur noch die Werte der Kanäle aus und weiter geht's mit dem nächsten Tick. Das Geraffel mit diesem Pseudo-Delay ist ja noch viel schlimmer als mehrere Timer!


Bei meiner kleinen DMX-Dimmer Software habe ich es allerdings noch anders gemacht. Dort habe ich alle Funktionen (im Wesentlichen Fades, aber mit unterschiedlichen Interpolationsarten) in nette kleine Klassen verpackt, die je eine Fade-Sequenz auf einem Kanal darstellen. Jede der Instanzen kennt ihren Anfangszeitpunkt relativ zum Abspielstart der Gesamtszene, und ihre Länge sowie Start- und Endwert. Ich habe es nun so gemacht, dass ich diese Klasse fragen kann: Welchen Wert hast du denn zum Zeitpunkt X? Die Klasse gibt mir einen Wert zurück, und somit brauche ich in meinem Play-Thread nur noch Aktuelle Uhrzeit minus Startuhrzeit nehmen, habe ein exaktes Delta, und frage einfach alle gerade aktiven Sequenzen, welchen Wert sie mir den geben möchten für dieses Delta. Das hübsch in ein Array, und weg damit über DMX.
Der riesen Vorteil: Ich bin komplett unabhängig vom konkreten Intervall, mit dem ich eine Szene abspiele. (Manche DMX-Konverter sind da etwas niggelich, deswegen habe ich ein SpinEdit mit dem man zwischen 5ms und 1000ms Intervallen verstellen kann - on the fly.)
Weiterer Vorteil: Man kann beliebig in einer Szene hin und her springen und bekommt die für den Zeitpunkt aktuellen Werte. In dem angehängten Bild habe ich z.B. die Trackbar direkt an die Position gezogen, und die kleinen Quadrate rechts der Kanäle zeigen den korrekten Wert (die sind direkt aus dem Output-Array gefärbt).

beanbear6 28. Aug 2014 20:20

AW: Zwei unabhängige Zeitschleifen D7
 
Hi Medium,
sorry ich versteh das nicht ganz. Wie krieg ich diese 2 oder 1 Sec unter??

DMX-Szenenanweisung Kanal1 Kanal2 Kanal3 ...
- 250 0
Fade to 90 Ch1 2sec 230 0
- 210 0
Fade to 100 Ch2 1sec 190 25
- 170 50

Die Scenen das hab ich nun im 250 ms Takt das geht auch ganz gut. Aber Du sagtest das geht alles ohne diesem dooofen Delay - aber wie?? Im übrigen dieses Programm (Dein bild) ist das in Delphi auch gemacht?
Gruß beanbear

Medium 29. Aug 2014 09:20

AW: Zwei unabhängige Zeitschleifen D7
 
Sieh den gesamten zeitlichen Ablauf mal durch nur einen einzigen Taktgeber bestimmt, und sowohl deine Szene als auch einzelne Fades als Arrays, deren Index in Zeit angegeben wird (mal so hypothetisch). Die eigentliche Hauptaufgabe ist es dann zu jedem Timer Event einfach nur die Werte der einzelnen Arrays zum DMX Interface zu schicken. Ein Array mit 4 Elementen würde bei 250ms Takt einer Sekunde entsprechen. Ich versuche mal Pseudocode. (Skizze in Pascal-Art, kein C&P fähiger Code.)

Delphi-Quellcode:
type
  TFadeBlock = class
  private
    FValues: array of Byte;
    FStartTime: Integer;
  public
    property StartTime: Integer;
    property Values[index: Integer]: Byte;
    constructor Create(aStartTime, aLengthInSec: Integer);
    function GetValueAtTime(aTime: Integer): Byte;
  end;

  TMyForm = class(TForm)
  private
    Channels: array[1..479] of TFadeBlock;
    Scene: array of TSceneEvent;
    CurrentTime: Integer;
  end;

implementation

constructor TFadeBlock.Create(aStartTime, aLengthInSec: Integer);
begin
  SetLength(FValues, aLengthInSec*(1/TimerInterval));
  FStartTime := aStartTime;
end;

function GetValueAtTime(aTime: Integer): Byte;
var
  i: Integer;
begin
  i := Max(Low(FValues), Min(aTime-FStartTime, High(FValues)));
  result := FValues[i];
end;

//--------------

procedure TMyForm.OnTimerEvent;
begin
  // Channel-Liste anhand von Szenenanweisungen mit Fade-Blöcken versehen
  if Assigned(SceneEvents[CurrentTime]) then
  begin
    Event := SceneEvents[CurrentTime];
    Channel := Event.Channel;
    Channels[Channel] := TFadeBlock.Create(CurrentTime, Event.LengthInSec);
    for i := 0 to High(Channels[Channel].Values) do // Internes Value-Array des Blocks mit den interpolierten Werten beschreiben, schöner wäre es noch wenn die Fade-Klasse dies selber täte
      Channels[Channel].Values[i] := Interpolate(Event.StartValue, Event.EndValue, i);
  end;
 
  // Nun einfach alle Kanäle "fragen" welchen Wert sie denn gerade haben, und den ausgeben
  for i := Low(Channels) to High(Channels) do
  begin
    if Assigned(Channels[i]) then
      OutputDMX(Channels[i].GetValueAtTime(CurrentTime), i);
  end;
 
  Inc(CurrentTime);
end;
Da das Szenen-Array ggf. etwas lang würde wenn man das Intervall kleiner macht (was sinnvoll wäre, da Fades mit 250ms nicht so toll aussehen), sollte man dafür vielleicht eher eine Liste nehmen, deren Index nicht der Zeit entspricht, sondern wo jeder Eintrag seine Startzeit als Feld bekommt. Dann muss man zwar pro Timer-Event alle Szenenanweisungen durchgehen, und schauen ob jetzt eine davon ansteht, aber das sollte selbst bei ein paar Tausend keine merkbare Performance kosten.

Und ja, das ist mit Delphi geschrieben. Da ich dafür TurboPower AsyncPro (COM-Port) nutze und dies nur für Delphi 7 parat hatte, ist es sogar noch Delphi 7.

beanbear6 30. Aug 2014 07:43

AW: Zwei unabhängige Zeitschleifen D7
 
Hi Medium,
ich werd mich jetzt mal durch deinen Quellcode wursteln, kann noch nicht alles umsetzen... Aber ich versuch das mal. Vielen vielen Dank Dir gleich mal für die Postings! Wird wohl ein paar Tage dauern bis ich mich dann nochmal melde. Also vielen Dank...
Gruß beanbear


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:18 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz