Entwickler-Ecke

Windows API - Tapi


Peter18 - Fr 21.11.14 14:37
Titel: Tapi
Ein freundliches Hallo an alle,

ich versuche die Tapi in den Griff zu bekommen, bleibe aber schon am Anfang hängen. Das Buch, das ich gekauft habe "Windows Telephony Programming A Developer's Guide to TAPI" (2 Monate Lieferzeit!) hilft leider nicht weiter oder ich sehe den Wald nicht, weil zu viele Bäume im Weg sind.

Ich habe ein Testprogramm erstellt, mit dem ich die TAPI und deren Funktionen testen möchte. Ich hänge aber schon bei der Initialisierung fest.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TForm1.Button1Click(Sender: TObject);
var
  Luh       : PHLineApp;
  DC        : Cardinal;    
  Lo, Hi, V : DWord;
  CCo, AC   : PChar;
  H         : HWND;
  R         : LongInt;   

begin
  Lo := 0;
  Hi := 0;
  R  := -2;
  R  := lineInitialize( Luh, Application.Handle, nil, PChar( 'Test' ), DC );  //  
  ShowMessage( 'Result:  ' + Inttostr( R ) + Char( $0D ) + 'Hex:  ' + IntToHex( R, 8 ) );

"lineInitialize" liefert einen Fehlercode: "-2147483595" (Hex: 80000035). Wenn ich den richtig interpretiere ist "Application.Handle" die Ursache. Aber weder "H" noch "Application.Handle" funktionieren. R erhält den gleichen Wert. Laut Buch sollte "Application.Handle" richtig sein.

Dieses Programm teste ich auf 2 Rechnern. Der eine ist mit einem Modem ausgretattet, der andere mit einer Fritz-Card. Mit direkten Aufruf von "tapiRequestMakeCall" wählt das Modem. Ich möchte aber nach der Initialisierung die vorhandenen Geräte ermitteln, damit ich je nach Rechner die richtigen Routinen verwenden kann.

Hat jemand einen Tipp auf Lager, der mich einen Schritt weiter bringt??

Grüße von der nebligen Nordsee

Peter


Gerd Kayser - Fr 21.11.14 17:02

user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
Hat jemand einen Tipp auf Lager, der mich einen Schritt weiter bringt??

Ich würde schauen wie es die Programmierer hier gemacht haben: http://sourceforge.net/projects/tpapro/


Peter18 - Mo 24.11.14 15:10

Hallo Gerd Kayser,

danke für den Hinweis. Dieses Beispiel hatte ich bei meiner Suche nicht gefunden. Die erste grobe Sichtung sieht so aus, als ob nur die Tapi 2 verwendet wird (Modem). Tapi 3 bietet weitergehende Möglichkeiten (Fritz).

Es wird wohl ein paar Tage dauern, das alles durchzusehen. Werde Berichten.

Falls jemand den Fehler erkennt würde ich mich sehr über eine Info freuen!

Grüße von der sonnigen Nordsee

Peter


Peter18 - Do 27.11.14 11:54

Ein freundliches hallo an alle,

leider hat mich der Tipp von Gerd Kayser noch nicht wirklich weiter gebracht. Die Funktion "lineInitialize" wird dort nicht verwendet und eine grobe Sichtung scheint darauf hinzudeuten, dass hier nur Modems betrieben werden. Beispielprogramme, die ich noch gefunfen habe führen jedenfalls zu einem Fehler, wenn sie auf einem Rechner ausgeführt werden, der mit einer Fritzcard ausgestattet ist aber nicht mit einem Modem. Auf einem Rechner mit Modem funktionieren sie jedoch.

Ich möchte eine Fritz-Karte ansteuern und sie eine Verbindung aufbauen lassen. Danach soll das Gespräch auf einen bestimmten Apparat durchgestellt werden. Weil ein Rechner mit Fritz und einer mit Moden ausgerüstet ist und ich das gleiche Programm auf beiden Rechnern verwenden möchte, will ich prüfen welche Geräte zur Verfügung stehen und sie entsprechend ansteuern. Laut Buch ist die Funktion dafür nötig.

In einem Beispiel für "lineInitialize" wurde die Funktion "AfxGetInstanceHandle" verwendet. Ist das Ergebnis mit "Application.Handle" identisch?? Die Funktion "AfxGetInstanceHandle" ist in der Delphi version nicht verfügbar. Die Beschreibung besagt, es handelt sich bei "Application.Handle" um ein Handle des Hauptfensters. MS spricht jedoch von der Anwendung. wenn beide identisch sind muß der Fehler bei einem anderen Parameter liegen.

Grüße von der Nordsee

Peter


baumina - Do 27.11.14 12:15

Ich habe ein Uralt-Modem und eine moderne Telefonanlage. Beides funktioniert bei mir mit folgemdem Aufruf:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
  
  FillChar(LineInitExParams, sizeof(LineInitExParams), 0);
  LineInitExParams.dwTotalSize := sizeof(LineInitExParams);
  dwAPIVersion := $10000000;
  Erg := lineInitializeEx(@lineApp, HInstance, lineCallback, PChar(Application.Name), lDeviceCount, dwAPIVersion, LineInitExParams);  { < 0 is an error }
  case Erg of
    LINEERR_INVALAPPNAME : aDialClass.AddInfo('LINEERR_INVALAPPNAME');
    LINEERR_OPERATIONFAILED : aDialClass.AddInfo('LINEERR_OPERATIONFAILED');
    LINEERR_INIFILECORRUPT : aDialClass.AddInfo('LINEERR_INIFILECORRUPT');
    LINEERR_INVALPOINTER : aDialClass.AddInfo('LINEERR_INVALPOINTER');
    LINEERR_REINIT : aDialClass.AddInfo('LINEERR_REINIT');
    LINEERR_NOMEM : aDialClass.AddInfo('LINEERR_NOMEM');
    LINEERR_INVALPARAM : aDialClass.AddInfo('LINEERR_INVALPARAM');
  end;



Delphi-Quelltext
1:
2:
3:
4:
5:
lineApp: THandle;
procedure LineCallback(hDevice, dwMsg, dwCallbackInstance, dwParam1, dwParam2, dwParam3: DWORD);
lDeviceCount : DWORD;
dwAPIVersion : DWORD;
LineInitExParams : TLineInitializeExParams;


Peter18 - Do 27.11.14 12:48

Hallo baumina,

ein ganz dickes Danke für Deine Antwort! Mit

Delphi-Quelltext
1:
R  := lineInitialize( @Luh, HInstance, @LineCallBack, PChar( 'Test' ), DC );                    

ist R = 0. Ein großer Schritt für den, der sich im Kreis dreht.

Steuerst Du die verschiedenen Geräte speziell an, oder macht das die Tapi automatisch?

Viele Grüße von der Nordsee

Peter


baumina - Do 27.11.14 12:54

Beim LineOpen musste ich unterscheiden:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
procedure TCustomTapiDial.OpenLine;
var
  extid   : TLineExtensionID;
  Hstr    : string;
  aResult : Integer; (*DWORD; *)

begin
  if LineApp = 0 then
  begin
    AddError(6);
    Exit;
  end;

  if lDeviceID < 0 then
  begin
    AddError(6);
    Exit;
  end;

 { Zeros CallParams structure }
  FillChar(CallParams, sizeof(CallParams), 0);
  CallParams.dwTotalSize := sizeof(CallParams);
  CallParams.dwBearerMode := LINEBEARERMODE_VOICE;
  CallParams.dwAddressMode := LINEADDRESSMODE_DIALABLEADDR;

  case lTAPIDialMode of
    ldmINTERACTIVEVOICE : CallParams.dwMediaMode := LINEMEDIAMODE_INTERACTIVEVOICE;
    ldmAUTOVOICE        : CallParams.dwMediaMode := LINEMEDIAMODE_AUTOMATEDVOICE;
    ldmDIGITALDATA      : CallParams.dwMediaMode := LINEMEDIAMODE_DIGITALDATA;
    ldmDATAMODEM        : CallParams.dwMediaMode := LINEMEDIAMODE_DATAMODEM;
    ldmVOICEVIEW        : CallParams.dwMediaMode := LINEMEDIAMODE_VOICEVIEW;
    else CallParams.dwMediaMode := LINEMEDIAMODE_INTERACTIVEVOICE;
  end;

  aResult := lineNegotiateAPIVersion(lineApp, lDeviceID, $00010000$10000000, tapiVersion, extid);
  if aResult < 0 then  { Check for version (copied from a TAPI sample) }
  begin
    AddErrorCode(aResult,2);
  end else  { Open a line for outbound calls (here I use first device, normally the modem) }
  begin
    aResult := lineOpen(lineApp,lDeviceID, @line, tapiVersion, 00,     { Zuerst Versuch ISDN }
                        LINECALLPRIVILEGE_MONITOR+LINECALLPRIVILEGE_OWNER,
                        LINEMEDIAMODE_INTERACTIVEVOICE, @CallParams);
    if aResult < 0 then
    begin
      aResult := lineOpen(lineApp, lDeviceID, @line, tapiVersion, 00,  { .. oder Modem }
                          LINECALLPRIVILEGE_MONITOR, 0, @CallParams);
    end;
    case aResult of
      LINEERR_ALLOCATED : aDialClass.AddInfo('LINEERR_ALLOCATED');
      LINEERR_LINEMAPPERFAILED : aDialClass.AddInfo('LINEERR_LINEMAPPERFAILED');
      LINEERR_BADDEVICEID : aDialClass.AddInfo('LINEERR_BADDEVICEID');
      LINEERR_NODRIVER : aDialClass.AddInfo('LINEERR_NODRIVER');
      LINEERR_INCOMPATIBLEAPIVERSION : aDialClass.AddInfo('LINEERR_INCOMPATIBLEAPIVERSION');
      LINEERR_NOMEM : aDialClass.AddInfo('LINEERR_INCOMPATIBLEAPIVERSION');
      LINEERR_INCOMPATIBLEEXTVERSION : aDialClass.AddInfo('LINEERR_INCOMPATIBLEEXTVERSION');
      LINEERR_OPERATIONFAILED : aDialClass.AddInfo('LINEERR_OPERATIONFAILED');
      LINEERR_INVALAPPHANDLE : aDialClass.AddInfo('LINEERR_INVALAPPHANDLE');
      LINEERR_RESOURCEUNAVAIL : aDialClass.AddInfo('LINEERR_RESOURCEUNAVAIL');
      LINEERR_INVALMEDIAMODE : aDialClass.AddInfo('LINEERR_INVALMEDIAMODE');
      LINEERR_STRUCTURETOOSMALL : aDialClass.AddInfo('LINEERR_STRUCTURETOOSMALL');
      LINEERR_INVALPOINTER : aDialClass.AddInfo('LINEERR_INVALPOINTER');
      LINEERR_UNINITIALIZED : aDialClass.AddInfo('LINEERR_UNINITIALIZED');
      LINEERR_INVALPRIVSELECT : aDialClass.AddInfo('LINEERR_INVALPRIVSELECT');
      LINEERR_REINIT : aDialClass.AddInfo('LINEERR_REINIT');
      LINEERR_NODEVICE : aDialClass.AddInfo('LINEERR_NODEVICE');
      LINEERR_OPERATIONUNAVAIL : aDialClass.AddInfo('LINEERR_OPERATIONUNAVAIL');
    end;
    if aResult < 0 then
    begin
      AddErrorCode(aResult,6);
      line := 0;
      Exit;
    end;
  end;

  aDialClass := self;
  lLineActive := True;
  Hstr := 'Opening: ';
  if (lDev.List.Count - 1) >= lDeviceId then Hstr := Hstr+lDev.List[lDeviceId];
  AddInfo(Hstr);
end;


Peter18 - Do 27.11.14 16:11

Hallo baumina,

nochmals Dank für Deine Antwort!

Wenn ich die Sache richtig sehe ist das Gerät in den Properties auf 0 eingestellt und der entscheidende Unterschied ist in "dwPrivileges" und "dwMediaModes" zu sehehen. Muß das Gespräch dann noch auf einen Apparat durchgestellt werden (ISDN) oder geschieht das automatisch?

Viele Grüße von der Nordsee

Peter


baumina - Do 27.11.14 16:34

Der TAPI-Treiber unserer Telefonanlage bringt mir über lineGetDevCaps die verschiedenen Telefonapparate zur Auswahl.


Peter18 - Do 27.11.14 16:47

Hallo baumina,

und nochmals Dank für Deine Antwort!

Unsere Anlage ist leider zu alt für eine Tapi. Dann muß ich wohl doch durchstellen.

Viele Grüße von der Nordsee

Peter


MSCH - Do 11.12.14 08:27

hallo,
andere Alternative; da die Tapi recht ausufernd ist, empfehle ich ich die Verwendung fertiger Komponenten, z.b. http://www.hbtapi.com. Man kann sich dann mehr auf die wirklichen Dinge konzentrieren 😃 das Teil kostet zwar Geld, funktioniert aber nach meiner bisherigen Erfahrung mit allen Tapi Treibern und Geräten.
und nein, ich bin kein Angestellter des Herstellers 😃😃
grez msch


Peter18 - Do 11.12.14 12:20

Hallo MSCH,

danke für den Hinweis, werde ich mir ansehen.

Grüße von der Nordsee

Peter