Jump to content

Kanalwechsel über SendMessage


Recommended Posts

Hallo zusammen,

 

ich versuche gerade herauszufinden, wie man über die SendMessage API

den aktuellen Kanal wechseln kann...

 

Die Nutzung des COM Interfaces scheidet leider in meinem konkreten

Fall aus... ;)

 

Hat jemand zufällig ein kleines Code-Beispiel für diesen Anwendungsfall

(Delphi Code bevorzugt) ?

 

gruß,

jnmarczi

Edited by Jnmarczi
Link to comment

Was ist an Daten verfügbar, um den Kanal zu identifizieren? Sind z.B. Tunertyp (DVB-S/T/C), Sendername, ServiceID und Audio-PID bekannt? Soll die Umschaltung durch ein anderes Programm (einen anderen Prozess) oder durch ein Plugin erfolgen?

Link to comment
Was ist an Daten verfügbar, um den Kanal zu identifizieren? Sind z.B. Tunertyp (DVB-S/T/C), Sendername, ServiceID und Audio-PID bekannt? Soll die Umschaltung durch ein anderes Programm (einen anderen Prozess) oder durch ein Plugin erfolgen?

 

Die Daten sind bekannt (Auslesen der channels.dat oder

mittels extra Config-Datei)...

 

Die Architektur ist derzeit noch ein kleines Problem, da habe ich

noch nicht den Dreh raus.

 

Das eigentliche "Programm" läuft als Com-Server, der in einem

Windows-Service gehostet wird. Dieser Service ist nur unter

LocalSystem-Account lauffähig (Umstellen auf einen User-Account

hat mir der Service mit einem schönen Absturz quittiert ;) )

Deswegen scheidet auch die Nutzung des COM-Interfaces aus,

da mein COM-Server den COM-Server vom DVBViewer gar

nicht "sieht", bzw. GetActiveObjekt nicht funktioniert.

 

Wenn die Umschaltung aus einem "anderen Prozess" klappt, würde

mich das weiterbringen. Wenn es nicht funktioniert, würde ich

ein DVBV Plugin schreiben und mal schauen wie ich das aus meinem

Com-Server anspreche (COM, Pipes, Sockets o.ä.)...

 

Gruß,

jnmarczi

Edited by Jnmarczi
Link to comment

Ok, am besten versuchst du es so:

 

1) Du stellst aus den Kanalparametern einen String zusammen, der das gleiche Format hat wie ein Kommandoparameter, mit dem man den DVBViewer dazu bewegt, einen Sender einzuschalten. Er enthält die ChannelID, die sich aus Name, Tunertyp, AudioPID und ServiceID zusammensetzt. Der DVBViewer identifiziert den dazugehörigen Sender in seiner Kanalliste fehlertolerant, d.h. selbst wenn eine der Angaben nicht stimmt oder fehlt, findet er meistens noch den richtigen Sender:

 

function BuildID(const Channel: TChannel): String;
begin
 with Channel, Tuner do
result := '-c' + Name + ':' +
  IntToStr(Int64((DWord(TunerType)+1) shl 29 + AudioPID shl 16 + SID));
end;

 

2) Du benutzt PostMessage, um dem DVBViewer den String zu senden. Da sowas prozessübergreifend mit Messages normalerweise nicht geht, hinterlegst du den String über die API-Funktion GlobalAddAtom für den DVBViewer und sendest ihm das "Atom" (also die String-ID), das die Funktion zurückgibt. Der DVBViewer holt den String dann mit GlobalGetAtomName ab, führt den Kommandoparameter aus und entfernt ihn mit GlobalDeleteAtom aus der entsprechenden Windows-Tabelle. Deshalb musst du sicherstellen, dass der DVBViewer dabei läuft, weil du sonst das OS zumüllst. Wenn das Handle des DVBViewer-Hauptfensters bereits ermittelt wurde (z.B. mit FindWindow), sieht der Code so aus:

 

const
 MSG_DVBCOMMANDPARAMS = WM_USER + 100;
var
 DVBViewerHandle: HWND;

PostMessage(DVBViewerHandle,MSG_DVBCOMMANDPARAMS,GlobalAddAtom(PChar(BuildID(Channel))),0);

 

Der EPGManager verwendet diese Methode, und auch der DVBViewer selbst, wenn man ihn (d.h. die gleiche Installation) ein zweites Mal mit einem Kommandoparemeter startet, um diesen an die schon laufende Instanz zu übergeben und sich danach sofort wieder zu beenden.

Link to comment

1. müsste man sehen, ob das geht, ein starten aus einem service heraus kann durchaus fatale folgen haben, besonders wenn der usermode =1 ist.

 

2. Wenn ich mich recht erinnere versagt Findwindow im service context, da der service keinen zugriff auf den userdesktop hat.

 

Das ganze ist nicht so einfach zu lösen, ich habe mich bei recordingservice mit einem plugin beholfen, das via shared memory mit dem service kommuniziert.

Link to comment
1. müsste man sehen, ob das geht, ein starten aus einem service heraus kann durchaus fatale folgen haben, besonders wenn der usermode =1 ist.

2. Wenn ich mich recht erinnere versagt Findwindow im service context, da der service keinen zugriff auf den userdesktop hat.

 

Danke Griga, danke Lars für die Tipps...

 

Ich werde das heute abend mal reinhacken...

 

@Lars: 2. funktioniert, wenn man dem Service und LocalSystem den Datenaustausch mit dem Destop erlaubt.

SendMessage funktioniert auch schon generell, d.h. ich habe schon Actions im DVBViewer durch den Service

ausgelöst.

 

Nur noch eine kurze Frage... Funktioniert das Auslesen des aktuellen Kanals auf ähnliche Weise???

 

Danke und Gruß,

jnmarczi

Link to comment
@Lars: 2. funktioniert, wenn man dem Service und LocalSystem den Datenaustausch mit dem Destop erlaubt.

Auch unter vista? ich bin der meinung dort ist das nicht mehr erlaubt.

Link to comment
Auch unter vista? ich bin der meinung dort ist das nicht mehr erlaubt.

 

Vorschlag eines Anfängers:

activedvbviewer = (DVBViewerServer.IDVBViewer)Marshal.GetActiveObject("DVBViewerServer.DVBViewer");

Link to comment
Auch unter vista? ich bin der meinung dort ist das nicht mehr erlaubt.

Stimmt, an Vista habe ich gar nicht gedacht ;) Da muss ich mir evtl.

noch was anderes ausdenken...

Link to comment
Auch unter vista? ich bin der meinung dort ist das nicht mehr erlaubt.

 

Hallo Lars,

 

danke nochmal für den Hinweis...

 

Ich werde das Problem nun mit einem Plugin lösen, das mit dem

Service über Named Pipes kommuniziert. Einen ersten Wurf hab'

schon runtergetippt... Ist allerdings noch sehr träge...

 

Gruß,

jnmarczi

Link to comment

Hallo nochmal,

 

der von Griga vorgeschlagene Weg funktioniert ganz gut... Allerdings dauert es vom PostMessage z.T. 7-8 sek. bis der DVBViewer wirklich

den Kanal wechselt (wäre für eine interaktive Fernbedienung ein bisschen zu träge :) )

 

Da ich jetzt - aufgrund des Hinweises von Lars - doch auf ein Plugin (und IPC mit dem Service) umgestiegen bin, wollte ich nachfragen

ob es noch eine andere Möglichkeit gibt?

 

Da ich nun auch wg. einem evtl. Usermode Problem auf eine eigene Konfiguration umgestiegen bin - um z.B. die Senderliste für die

Philips FB zu speichern - kann ich mir jede dafür benötigte Information vorhalten.

 

Oder empfiehlt Ihr an dieser Stelle die Verwendung des COM Interfaces in einem Plugin?

 

gruß,

jnmarczi

Link to comment
Oder empfiehlt Ihr an dieser Stelle die Verwendung des COM Interfaces in einem Plugin?

 

Wenn die gewünschte DVBV-Funktionalität aus dem Plugin heraus realisierbar ist macht COM keinen Sinn - weil 1. noch mehr Performanceverlust und 2. der DVBV GE nicht mehr verwendet werden kann.

 

der von Griga vorgeschlagene Weg funktioniert ganz gut... Allerdings dauert es vom PostMessage z.T. 7-8 sek. bis der DVBViewer wirklich

den Kanal wechselt (wäre für eine interaktive Fernbedienung ein bisschen zu träge :) )

 

Hmm, 7-8 sek erscheint mir trotz Pipes-IPC nun doch ein wenig lang. Du solltest mal feststellen wo dieser Performanceverlust wirklich herkommt. Wenns wirklich die Pipes sind (werden die etwa gepollt?) gibst ja noch andere Oprionen für die IPC - Shared Medmory etwa.

 

mfg erwin

Link to comment
Wenns wirklich die Pipes sind (werden die etwa gepollt?) gibst ja noch andere Oprionen für die IPC - Shared Medmory etwa.

Hallo Erwin,

 

ja, die Pipes werden per Timer gepollt...

Ich werde zur Sicherheit mal das Plugin deaktivieren und PostMessage

aus einer anderen Applikation absetzen. Mal schauen, ob es dann schneller

geht.

 

Wenn das bottleneck doch PostMessage ist, was dann?

 

Gruß,

jnmarczi

Edited by Jnmarczi
Link to comment
der von Griga vorgeschlagene Weg funktioniert ganz gut... Allerdings dauert es vom PostMessage z.T. 7-8 sek. bis der DVBViewer wirklich

den Kanal wechselt (wäre für eine interaktive Fernbedienung ein bisschen zu träge :) )

 

Noch ein par Anregungen.

 

const
 MSG_DVBCOMMANDPARAMS = WM_USER + 100;
var
 DVBViewerHandle: HWND;

PostMessage(DVBViewerHandle,MSG_DVBCOMMANDPARAMS,GlobalAddAtom(PChar(BuildID(Channel))),0);

 

Wenn Du aus einem DVBV-Plugin heraus operierst, brauchst Du den Umweg über GlobalAddAtom() nicht.

 

const
 MSG_CHANNELSWITCH = ???;
var
 DVBViewerHandle: HWND;

 CHANNELSWITCH_DATA: channel.

PostMessage(DVBViewerHandle,MSG_CHANNELSWITCH,channel,0);

 

Auch entfällt das Parsen des übergebenen Kommandozeilenparameters. Du brauchst hierfür den Wert für MSG_CHANNELSWITCH (oder wie ihn die DVBV-Entwickler nennen) und die Beschreibung der zugehörigen Datenstruktur/Datenstrings aus dem SDK. Habs zwar dort nicht gefunden aber vielleicht schauen hier die Entwickler noch mal vorbei.

 

mfg erwin

Link to comment
Wenn Du aus einem DVBV-Plugin heraus operierst, brauchst Du den Umweg über GlobalAddAtom() nicht.

Auch entfällt das Parsen des übergebenen Kommandozeilenparameters.

Das sind alles nur Millisekunden. Wenn ich hier eine DVBViewer-Verknüpfung mit einem Kommandoparameter erzeuge, der auf einen bestimmten Sender umschaltet, geht das nach einem Doppelklick darauf bei laufendem DVBViewer Pro in zwei bis drei Sekunden über die Bühne. Und dabei muss sogar eine zweite DVBViewer-Instanz von der Festplatte geladen und gestartet werden, die dann der ersten wie beschrieben den Kommandoparameter übermittelt.

 

Die Verzögerung dürfte deshalb eine andere Ursache haben.

Link to comment
Das sind alles nur Millisekunden. Wenn ich hier eine DVBViewer-Verknüpfung mit einem Kommandoparameter erzeuge, der auf einen bestimmten Sender umschaltet, geht das nach einem Doppelklick darauf bei laufendem DVBViewer Pro in zwei bis drei Sekunden über die Bühne. Und dabei muss sogar eine zweite DVBViewer-Instanz von der Festplatte geladen und gestartet werden, die dann der ersten wie beschrieben den Kommandoparameter übermittelt.

 

Die Verzögerung dürfte deshalb eine andere Ursache haben.

 

Sehe ich auch so

 

mfg erwin

Link to comment
Die Verzögerung dürfte deshalb eine andere Ursache haben.

 

Hatte Sie, ich hatte noch eine Plugin-Leiche von meinen kläglichen Entwicklungsversuchen

im Plugins-Verzeichnis...

 

...DVBViewer-Verknüpfung mit einem Kommandoparameter erzeuge...

 

@Griga: Du bist meine Inspiration... :) Um es erst einmal zum Laufen zu bringen und mich

nicht in Pipes, MMF o.ä. zu verzetteln, habe ich eine "ähnliche" Lösung gewählt.

Aus dem Service heraus wird nun mittels CreateProcessAsUser eine Applikation

im User-Kontext gestartet, die dann die Kommandos an den DVBViewer per

PostMessage/SendMessage sendet.

Auf diese Weise kann ich nun auch den DVBViewer selbst im User-Kontext

starten, falls er noch nicht läuft.

 

Danke und Gruß,

jnmarczi

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...