Rev 4 | Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | daniel-mar | 1 | unit DXPlay; |
2 | |||
3 | interface |
||
4 | |||
5 | {$INCLUDE DelphiXcfg.inc} |
||
6 | |||
7 | uses |
||
8 | Windows, SysUtils, Classes, Forms, DXClass, ActiveX, DirectX, DXETable; |
||
9 | |||
10 | type |
||
11 | |||
12 | { TDXPlayPlayer } |
||
13 | |||
14 | TDXPlayPlayer = class(TCollectionItem) |
||
15 | private |
||
16 | FData: Pointer; |
||
17 | FID: TDPID; |
||
18 | FName: string; |
||
19 | FRemotePlayer: Boolean; |
||
20 | public |
||
21 | property Data: Pointer read FData write FData; |
||
22 | property ID: TDPID read FID; |
||
23 | property Name: string read FName; |
||
24 | property RemotePlayer: Boolean read FRemotePlayer; |
||
25 | end; |
||
26 | |||
27 | { TDXPlayPlayers } |
||
28 | |||
29 | TDXPlayPlayers = class(TCollection) |
||
30 | private |
||
31 | function GetPlayer(Index: Integer): TDXPlayPlayer; |
||
32 | public |
||
33 | constructor Create; |
||
34 | function Find(ID: TDPID): TDXPlayPlayer; |
||
35 | function IndexOf(ID: TDPID): Integer; |
||
36 | property Players[Index: Integer]: TDXPlayPlayer read GetPlayer; default; |
||
37 | end; |
||
38 | |||
39 | { TDXPlayModemSetting } |
||
40 | |||
41 | TDXPlayModemSetting = class(TPersistent) |
||
42 | private |
||
43 | FEnabled: Boolean; |
||
44 | FPhoneNumber: string; |
||
45 | FModemName: string; |
||
46 | FModemNames: TStrings; |
||
47 | function GetModemNames: TStrings; |
||
48 | public |
||
49 | destructor Destroy; override; |
||
50 | procedure Assign(Source: TPersistent); override; |
||
51 | property ModemName: string read FModemName write FModemName; |
||
52 | property ModemNames: TStrings read GetModemNames; |
||
53 | published |
||
54 | property Enabled: Boolean read FEnabled write FEnabled; |
||
55 | property PhoneNumber: string read FPhoneNumber write FPhoneNumber; |
||
56 | end; |
||
57 | |||
58 | { TDXPlayTCPIPSetting } |
||
59 | |||
60 | TDXPlayTCPIPSetting = class(TPersistent) |
||
61 | private |
||
62 | FEnabled: Boolean; |
||
63 | FHostName: string; |
||
64 | FPort: Word; |
||
65 | public |
||
66 | procedure Assign(Source: TPersistent); override; |
||
67 | published |
||
68 | property Enabled: Boolean read FEnabled write FEnabled; |
||
69 | property HostName: string read FHostName write FHostName; |
||
70 | property Port: Word read FPort write FPort; |
||
71 | end; |
||
72 | |||
73 | { EDXPlayError } |
||
74 | |||
75 | EDXPlayError = class(Exception); |
||
76 | |||
77 | { TCustomDXPlay } |
||
78 | |||
79 | TDXPlayEvent = procedure(Sender: TObject; Player: TDXPlayPlayer) of object; |
||
80 | |||
81 | TDXPlayMessageEvent = procedure(Sender: TObject; From: TDXPlayPlayer; |
||
82 | Data: Pointer; DataSize: Integer) of object; |
||
83 | |||
84 | TDXPlaySendCompleteResult = (crOk, crAbort, crGeneric); |
||
85 | |||
86 | TDXPlaySendCompleteEvent = procedure(Sender: TObject; MessageID: DWORD; |
||
87 | Result: TDXPlaySendCompleteResult; SendTime: Integer) of object; |
||
88 | |||
89 | TCustomDXPlay = class(TComponent) |
||
90 | private |
||
91 | FDPlay: IDirectPlay4A; |
||
92 | FGUID: string; |
||
93 | FIsHost: Boolean; |
||
94 | FLocalPlayer: TDXPlayPlayer; |
||
95 | FMaxPlayers: Integer; |
||
96 | FPlayers: TDXPlayPlayers; |
||
97 | FCalledDoOpen: Boolean; |
||
98 | FOnAddPlayer: TDXPlayEvent; |
||
99 | FOnClose: TNotifyEvent; |
||
100 | FOnDeletePlayer: TDXPlayEvent; |
||
101 | FOnMessage: TDXPlayMessageEvent; |
||
102 | FOnOpen: TNotifyEvent; |
||
103 | FOnSendComplete: TDXPlaySendCompleteEvent; |
||
104 | FOnSessionLost: TNotifyEvent; |
||
105 | FOpened: Boolean; |
||
106 | FRecvEvent: array[0..1] of THandle; |
||
107 | FRecvThread: TThread; |
||
108 | FInThread: Boolean; |
||
109 | FProviderName: string; |
||
110 | FProviders: TStrings; |
||
111 | FSessionName: string; |
||
112 | FSessions: TStrings; |
||
113 | FReadSessioned: Boolean; |
||
114 | FModemSetting: TDXPlayModemSetting; |
||
115 | FTCPIPSetting: TDXPlayTCPIPSetting; |
||
116 | FAsync: Boolean; |
||
117 | FAsyncSupported: Boolean; |
||
118 | procedure ChangeDPlay; |
||
119 | procedure CreateDPlayWithoutDialog(out DPlay: IDirectPlay4A; const ProviderName: string); |
||
120 | function OpenDPlayWithLobby(out Name: string): Boolean; |
||
121 | function OpenDPlayWithoutLobby(out Name: string): Boolean; |
||
122 | function OpenDPlayWithoutLobby2(const NewSession: Boolean; const ProviderName, SessionName, PlayerName: string): Boolean; |
||
123 | procedure Open_(NameS: string); |
||
124 | procedure ReceiveMessage; |
||
125 | function GetProviders: TStrings; |
||
126 | function GetSessionsPty: TStrings; |
||
127 | procedure ClearSessionList; |
||
128 | procedure SetGUID(const Value: string); |
||
129 | procedure SetModemSetting(Value: TDXPlayModemSetting); |
||
130 | procedure SetProviderName(const Value: string); |
||
131 | procedure SetTCPIPSetting(Value: TDXPlayTCPIPSetting); |
||
132 | protected |
||
133 | procedure DoAddPlayer(Player: TDXPlayPlayer); virtual; |
||
134 | procedure DoClose; virtual; |
||
135 | procedure DoDeletePlayer(Player: TDXPlayPlayer); virtual; |
||
136 | procedure DoMessage(From: TDXPlayPlayer; Data: Pointer; DataSize: Integer); virtual; |
||
137 | procedure DoOpen; virtual; |
||
138 | procedure DoSessionLost; virtual; |
||
139 | procedure DoSendComplete(MessageID: DWORD; Result: TDXPlaySendCompleteResult; |
||
140 | SendTime: Integer); virtual; |
||
141 | public |
||
142 | constructor Create(AOwner: TComponent); override; |
||
143 | destructor Destroy; override; |
||
144 | procedure Close; |
||
145 | procedure Open; |
||
146 | procedure Open2(NewSession: Boolean; const SessionName, PlayerName: string); |
||
147 | function GetProviderNameFromGUID(const ProviderGUID: TGUID): string; |
||
148 | procedure GetSessions; |
||
149 | procedure SendMessage(ToID: TDPID; Data: Pointer; DataSize: Integer); |
||
150 | function SendMessageEx(ToID: TDPID; Data: Pointer; DataSize: Integer; |
||
151 | dwFlags: DWORD): DWORD; |
||
152 | property GUID: string read FGUID write SetGUID; |
||
153 | property IsHost: Boolean read FIsHost; |
||
154 | property LocalPlayer: TDXPlayPlayer read FLocalPlayer; |
||
155 | property MaxPlayers: Integer read FMaxPlayers write FMaxPlayers; |
||
156 | property OnAddPlayer: TDXPlayEvent read FOnAddPlayer write FOnAddPlayer; |
||
157 | property OnClose: TNotifyEvent read FOnClose write FOnClose; |
||
158 | property OnDeletePlayer: TDXPlayEvent read FOnDeletePlayer write FOnDeletePlayer; |
||
159 | property OnMessage: TDXPlayMessageEvent read FOnMessage write FOnMessage; |
||
160 | property OnOpen: TNotifyEvent read FOnOpen write FOnOpen; |
||
161 | property OnSendComplete: TDXPlaySendCompleteEvent read FOnSendComplete write FOnSendComplete; |
||
162 | property OnSessionLost: TNotifyEvent read FOnSessionLost write FOnSessionLost; |
||
163 | property Opened: Boolean read FOpened; |
||
164 | property Players: TDXPlayPlayers read FPlayers; |
||
165 | property ProviderName: string read FProviderName write SetProviderName; |
||
166 | property Providers: TStrings read GetProviders; |
||
167 | property SessionName: string read FSessionName; |
||
168 | property Sessions: TStrings read GetSessionsPty; |
||
169 | property ModemSetting: TDXPlayModemSetting read FModemSetting write SetModemSetting; |
||
170 | property TCPIPSetting: TDXPlayTCPIPSetting read FTCPIPSetting write SetTCPIPSetting; |
||
171 | property Async: Boolean read FAsync write FAsync; |
||
172 | property AsyncSupported: Boolean read FAsyncSupported; |
||
173 | end; |
||
174 | |||
175 | TDXPlay = class(TCustomDXPlay) |
||
176 | published |
||
177 | property Async; |
||
178 | property GUID; |
||
179 | property MaxPlayers; |
||
180 | property ModemSetting; |
||
181 | property TCPIPSetting; |
||
182 | property OnAddPlayer; |
||
183 | property OnClose; |
||
184 | property OnDeletePlayer; |
||
185 | property OnMessage; |
||
186 | property OnOpen; |
||
187 | property OnSendComplete; |
||
188 | property OnSessionLost; |
||
189 | end; |
||
190 | |||
191 | function DXPlayMessageType(P: Pointer): DWORD; |
||
192 | |||
193 | function DXPlayStringToGUID(const S: string): TGUID; |
||
194 | function DXDirectPlayCreate(const lpGUID: TGUID; out lplpDP: IDirectPlay; |
||
195 | pUnk: IUnknown): HRESULT; |
||
196 | |||
197 | implementation |
||
198 | |||
199 | uses DXPlayFm, DXConsts; |
||
200 | |||
201 | function DXPlayMessageType(P: Pointer): DWORD; |
||
202 | begin |
||
203 | Result := PDPMSG_GENERIC(P)^.dwType; |
||
204 | end; |
||
205 | |||
206 | function DXPlayStringToGUID(const S: string): TGUID; |
||
207 | var |
||
208 | ErrorCode: Integer; |
||
209 | begin |
||
210 | ErrorCode := CLSIDFromString(PWideChar(WideString(S)), Result); |
||
211 | if ErrorCode<0 then |
||
212 | raise EDXPlayError.Create(WindowsErrorMsg(ErrorCode)); |
||
213 | end; |
||
214 | |||
215 | function GUIDToString(const ClassID: TGUID): string; |
||
216 | var |
||
217 | ErrorCode: Integer; |
||
218 | P: PWideChar; |
||
219 | begin |
||
220 | ErrorCode := StringFromCLSID(ClassID, P); |
||
221 | if ErrorCode<0 then |
||
222 | raise EDXPlayError.Create(WindowsErrorMsg(ErrorCode)); |
||
223 | Result := P; |
||
224 | CoTaskMemFree(P); |
||
225 | end; |
||
226 | |||
227 | function DXDirectPlayCreate(const lpGUID: TGUID; out lplpDP: IDirectPlay; |
||
228 | pUnk: IUnknown): HRESULT; |
||
229 | type |
||
230 | TDirectPlayCreate= function(const lpGUID: TGUID; out lplpDP: IDirectPlay; pUnk: IUnknown): HRESULT; stdcall; |
||
231 | begin |
||
232 | Result := TDirectPlayCreate(DXLoadLibrary('DPlayX.dll', 'DirectPlayCreate')) |
||
233 | (lpGUID, lplpDP, pUnk); |
||
234 | end; |
||
235 | |||
236 | function DXDirectPlayEnumerateA(lpEnumDPCallback: TDPEnumDPCallbackA; lpContext: Pointer): HRESULT; |
||
237 | type |
||
238 | TDirectPlayEnumerateA= function(lpEnumDPCallback: TDPEnumDPCallbackA; lpContext: Pointer): HRESULT; stdcall; |
||
239 | begin |
||
240 | Result := TDirectPlayEnumerateA(DXLoadLibrary('DPlayX.dll', 'DirectPlayEnumerateA')) |
||
241 | (lpEnumDPCallback, lpContext); |
||
242 | end; |
||
243 | |||
244 | function DXDirectPlayLobbyCreateA(const lpguidSP: TGUID; out lplpDPL: IDirectPlayLobbyA; |
||
245 | lpUnk: IUnknown; lpData: Pointer; dwDataSize: DWORD): HRESULT; |
||
246 | type |
||
247 | TDirectPlayLobbyCreateA = function(const lpguidSP: TGUID; out lplpDPL: IDirectPlayLobbyA; |
||
248 | lpUnk: IUnknown; lpData: Pointer; dwDataSize: DWORD): HRESULT; stdcall; |
||
249 | begin |
||
250 | Result := TDirectPlayLobbyCreateA(DXLoadLibrary('DPlayX.dll', 'DirectPlayLobbyCreateA')) |
||
251 | (lpguidSP, lplpDPL, lpUnk, lpData, dwDataSize); |
||
252 | end; |
||
253 | |||
254 | { TDXPlayPlayers } |
||
255 | |||
256 | constructor TDXPlayPlayers.Create; |
||
257 | begin |
||
258 | inherited Create(TDXPlayPlayer); |
||
259 | end; |
||
260 | |||
261 | function TDXPlayPlayers.Find(ID: TDPID): TDXPlayPlayer; |
||
262 | var |
||
263 | i: Integer; |
||
264 | begin |
||
265 | i := IndexOf(ID); |
||
266 | if i=-1 then |
||
267 | raise EDXPlayError.Create(SDXPlayPlayerNotFound); |
||
268 | Result := Players[i]; |
||
269 | end; |
||
270 | |||
271 | function TDXPlayPlayers.IndexOf(ID: TDPID): Integer; |
||
272 | var |
||
273 | i: Integer; |
||
274 | begin |
||
275 | for i:=0 to Count-1 do |
||
276 | if Players[i].FID=ID then |
||
277 | begin |
||
278 | Result := i; |
||
279 | Exit; |
||
280 | end; |
||
281 | Result := -1; |
||
282 | end; |
||
283 | |||
284 | function TDXPlayPlayers.GetPlayer(Index: Integer): TDXPlayPlayer; |
||
285 | begin |
||
286 | Result := TDXPlayPlayer(Items[Index]); |
||
287 | end; |
||
288 | |||
289 | { TDXPlayModemSetting } |
||
290 | |||
291 | destructor TDXPlayModemSetting.Destroy; |
||
292 | begin |
||
293 | FModemNames.Free; |
||
294 | inherited Destroy; |
||
295 | end; |
||
296 | |||
297 | procedure TDXPlayModemSetting.Assign(Source: TPersistent); |
||
298 | begin |
||
299 | if Source is TDXPlayModemSetting then |
||
300 | begin |
||
301 | FEnabled := TDXPlayModemSetting(Source).FEnabled; |
||
302 | FPhoneNumber := TDXPlayModemSetting(Source).FPhoneNumber; |
||
303 | FModemName := TDXPlayModemSetting(Source).FModemName; |
||
304 | end else |
||
305 | inherited Assign(Source); |
||
306 | end; |
||
307 | |||
308 | function TDXPlayModemSetting.GetModemNames: TStrings; |
||
309 | |||
310 | function EnumModemAddress(const guidDataType: TGUID; |
||
311 | dwDataSize: DWORD; lpData: Pointer; lpContext: Pointer): BOOL; stdcall; |
||
312 | begin |
||
313 | if CompareMem(@guidDataType, @DPAID_Modem, SizeOf(TGUID)) then |
||
314 | TStrings(lpContext).Add( PChar(lpData)); |
||
315 | Result := True; |
||
316 | end; |
||
317 | |||
318 | var |
||
319 | Lobby1: IDirectPlayLobbyA; |
||
320 | Lobby: IDirectPlayLobby2A; |
||
321 | DPlay1: IDirectPlay; |
||
322 | DPlay: IDirectPlay4A; |
||
323 | lpAddress: Pointer; |
||
324 | dwAddressSize: DWORD; |
||
325 | begin |
||
326 | if FModemNames=nil then |
||
327 | begin |
||
328 | FModemNames := TStringList.Create; |
||
329 | try |
||
330 | if DXDirectPlayLobbyCreateA(PGUID(nil)^, Lobby1, nil, nil, 0)<>0 then |
||
331 | raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]); |
||
332 | Lobby := Lobby1 as IDirectPlayLobby2A; |
||
333 | |||
334 | if DXDirectPlayCreate(DPSPGUID_MODEM, DPlay1, nil)<>0 then |
||
335 | raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]); |
||
336 | DPlay := DPlay1 as IDirectPlay4A; |
||
337 | |||
338 | { get size of player address for all players } |
||
339 | if DPlay.GetPlayerAddress(DPID_ALLPLAYERS, nil^, dwAddressSize)<>DPERR_BUFFERTOOSMALL then |
||
340 | raise EDXPlayError.Create(SDXPlayModemListCannotBeAcquired); |
||
341 | |||
342 | GetMem(lpAddress, dwAddressSize); |
||
343 | try |
||
344 | FillChar(lpAddress^, dwAddressSize, 0); |
||
345 | |||
346 | { get the address } |
||
347 | if DPlay.GetPlayerAddress(DPID_ALLPLAYERS, lpAddress^, dwAddressSize)<>0 then |
||
348 | raise EDXPlayError.Create(SDXPlayModemListCannotBeAcquired); |
||
349 | |||
350 | { get modem strings from address and put them in the combo box } |
||
351 | if Lobby.EnumAddress(@EnumModemAddress, lpAddress^, dwAddressSize, FModemNames)<>0 then |
||
352 | raise EDXPlayError.Create(SDXPlayModemListCannotBeAcquired); |
||
353 | finally |
||
354 | FreeMem(lpAddress); |
||
355 | end; |
||
356 | except |
||
357 | FModemNames.Free; FModemNames := nil; |
||
358 | raise; |
||
359 | end; |
||
360 | end; |
||
361 | |||
362 | Result := FModemNames; |
||
363 | end; |
||
364 | |||
365 | { TDXPlayTCPIPSetting } |
||
366 | |||
367 | procedure TDXPlayTCPIPSetting.Assign(Source: TPersistent); |
||
368 | begin |
||
369 | if Source is TDXPlayTCPIPSetting then |
||
370 | begin |
||
371 | FEnabled := TDXPlayTCPIPSetting(Source).FEnabled; |
||
372 | FHostName := TDXPlayTCPIPSetting(Source).FHostName; |
||
373 | end else |
||
374 | inherited Assign(Source); |
||
375 | end; |
||
376 | |||
377 | { TCustomDXPlay } |
||
378 | |||
379 | constructor TCustomDXPlay.Create(AOwner: TComponent); |
||
380 | begin |
||
381 | inherited Create(AOwner); |
||
382 | FPlayers := TDXPlayPlayers.Create; |
||
383 | FModemSetting := TDXPlayModemSetting.Create; |
||
384 | FTCPIPSetting := TDXPlayTCPIPSetting.Create; |
||
385 | FSessions := TStringList.Create; |
||
386 | |||
387 | FGUID := GUIDToString(GUID_NULL); |
||
388 | FMaxPlayers := 0; |
||
389 | end; |
||
390 | |||
391 | destructor TCustomDXPlay.Destroy; |
||
392 | var |
||
393 | i: Integer; |
||
394 | begin |
||
395 | Close; |
||
396 | |||
397 | FPlayers.Free; |
||
398 | |||
399 | if FProviders<>nil then |
||
400 | begin |
||
401 | for i:=0 to FProviders.Count-1 do |
||
402 | Dispose(PGUID(FProviders.Objects[i])); |
||
403 | end; |
||
404 | FProviders.Free; |
||
405 | FModemSetting.Free; |
||
406 | FTCPIPSetting.Free; |
||
407 | ClearSessionList; |
||
408 | FSessions.Free; |
||
409 | inherited Destroy; |
||
410 | end; |
||
411 | |||
412 | type |
||
413 | TDXPlayRecvThread = class(TThread) |
||
414 | private |
||
415 | FDXPlay: TCustomDXPlay; |
||
416 | constructor Create(DXPlay: TCustomDXPlay); |
||
417 | destructor Destroy; override; |
||
418 | procedure Execute; override; |
||
419 | end; |
||
420 | |||
421 | constructor TDXPlayRecvThread.Create(DXPlay: TCustomDXPlay); |
||
422 | begin |
||
423 | FDXPlay := DXPlay; |
||
424 | |||
425 | FDXPlay.FRecvEvent[1] := CreateEvent(nil, False, False, nil); |
||
426 | |||
427 | FreeOnTerminate := True; |
||
428 | inherited Create(True); |
||
429 | end; |
||
430 | |||
431 | destructor TDXPlayRecvThread.Destroy; |
||
432 | begin |
||
433 | FreeOnTerminate := False; |
||
434 | SetEvent(FDXPlay.FRecvEvent[1]); |
||
435 | |||
436 | inherited Destroy; |
||
437 | |||
438 | CloseHandle(FDXPlay.FRecvEvent[1]); |
||
439 | |||
440 | FDXPlay.FRecvThread := nil; |
||
441 | FDXPlay.Close; |
||
442 | end; |
||
443 | |||
444 | procedure TDXPlayRecvThread.Execute; |
||
445 | begin |
||
446 | while WaitForMultipleObjects(2, @FDXPlay.FRecvEvent, False, INFINITE)=WAIT_OBJECT_0 do |
||
447 | begin |
||
448 | Synchronize(FDXPlay.ReceiveMessage); |
||
449 | end; |
||
450 | end; |
||
451 | |||
452 | procedure TCustomDXPlay.ReceiveMessage; |
||
453 | var |
||
454 | idFrom, idTo: DWORD; |
||
455 | hr: HRESULT; |
||
456 | lpvMsgBuffer: Pointer; |
||
457 | dwMsgBufferSize: DWORD; |
||
458 | Msg_CreatePlayerOrGroup: PDPMSG_CREATEPLAYERORGROUP; |
||
459 | Msg_DeletePlayerOrGroup: PDPMSG_DESTROYPLAYERORGROUP; |
||
460 | Msg_SendComplete: PDPMsg_SendComplete; |
||
461 | SendCompleteResult: TDXPlaySendCompleteResult; |
||
462 | Player: TDXPlayPlayer; |
||
463 | i: Integer; |
||
464 | begin |
||
465 | FInThread := True; |
||
466 | try |
||
467 | try |
||
468 | lpvMsgBuffer := nil; |
||
469 | dwMsgBufferSize := 0; |
||
470 | |||
471 | try |
||
472 | repeat |
||
473 | hr := FDPlay.Receive(idFrom, idTo, DPRECEIVE_ALL, lpvMsgBuffer^, dwMsgBufferSize); |
||
474 | |||
475 | if hr=DPERR_BUFFERTOOSMALL then |
||
476 | begin |
||
477 | ReAllocMem(lpvMsgBuffer, dwMsgBufferSize); |
||
478 | hr := FDPlay.Receive(idFrom, idTo, DPRECEIVE_ALL, lpvMsgBuffer^, dwMsgBufferSize); |
||
479 | end; |
||
480 | |||
481 | if (hr=0) and (dwMsgBufferSize>=SizeOf(TDPMSG_GENERIC)) then |
||
482 | begin |
||
483 | if idFrom=DPID_SYSMSG then |
||
484 | begin |
||
485 | { System message } |
||
486 | case PDPMSG_GENERIC(lpvMsgBuffer)^.dwType of |
||
487 | DPSYS_CREATEPLAYERORGROUP: |
||
488 | begin |
||
489 | { New player } |
||
490 | Msg_CreatePlayerOrGroup := lpvMsgBuffer; |
||
491 | |||
492 | if Msg_CreatePlayerOrGroup.DPID<>FLocalPlayer.FID then |
||
493 | begin |
||
494 | Player := TDXPlayPlayer.Create(Players); |
||
495 | Player.FID := Msg_CreatePlayerOrGroup.DPID; |
||
496 | Player.FRemotePlayer := True; |
||
497 | |||
498 | with Msg_CreatePlayerOrGroup.dpnName do |
||
499 | begin |
||
500 | if lpszShortNameA<>nil then |
||
501 | Player.FName := lpszShortNameA; |
||
502 | end; |
||
503 | |||
504 | DoAddPlayer(Player); |
||
505 | end; |
||
506 | end; |
||
507 | DPSYS_DESTROYPLAYERORGROUP: |
||
508 | begin |
||
509 | { Player deletion } |
||
510 | Msg_DeletePlayerOrGroup := lpvMsgBuffer; |
||
511 | |||
512 | if Msg_DeletePlayerOrGroup.DPID<>FLocalPlayer.FID then |
||
513 | begin |
||
514 | i := Players.IndexOf(Msg_DeletePlayerOrGroup.DPID); |
||
515 | if i<>-1 then |
||
516 | begin |
||
517 | Player := Players[i]; |
||
518 | DoDeletePlayer(Player); |
||
519 | Player.Free; |
||
520 | end; |
||
521 | end; |
||
522 | end; |
||
523 | DPSYS_SESSIONLOST: |
||
524 | begin |
||
525 | { The session was lost. } |
||
526 | DoSessionLost; |
||
527 | Close; |
||
528 | end; |
||
529 | DPSYS_HOST: |
||
530 | begin |
||
531 | { Here became a host. } |
||
532 | FIsHost := True; |
||
533 | end; |
||
534 | DPSYS_SENDCOMPLETE: |
||
535 | begin |
||
536 | { Send complete } |
||
537 | Msg_SendComplete := lpvMsgBuffer; |
||
538 | if Msg_SendComplete.idFrom=FLocalPlayer.FID then |
||
539 | begin |
||
540 | case Msg_SendComplete.hr of |
||
541 | DP_OK : SendCompleteResult := crOk; |
||
542 | DPERR_ABORTED: SendCompleteResult := crAbort; |
||
543 | else SendCompleteResult := crGeneric; |
||
544 | end; |
||
545 | |||
546 | DoSendComplete(Msg_SendComplete^.dwMsgID, SendCompleteResult, Msg_SendComplete^.dwSendTime); |
||
547 | end; |
||
548 | end; |
||
549 | end; |
||
550 | end else |
||
551 | begin |
||
552 | { Application definition message } |
||
553 | DoMessage(Players.Find(idFrom), lpvMsgBuffer, dwMsgBufferSize); |
||
554 | end; |
||
555 | end; |
||
556 | until hr<>0; |
||
557 | finally |
||
558 | FreeMem(lpvMsgBuffer); |
||
559 | end; |
||
560 | except |
||
561 | on E: Exception do |
||
562 | Application.HandleException(E); |
||
563 | end; |
||
564 | finally |
||
565 | FInThread := False; |
||
566 | end; |
||
567 | end; |
||
568 | |||
569 | procedure TCustomDXPlay.DoAddPlayer(Player: TDXPlayPlayer); |
||
570 | begin |
||
571 | if Assigned(FOnAddPlayer) then FOnAddPlayer(Self, Player) |
||
572 | end; |
||
573 | |||
574 | procedure TCustomDXPlay.DoClose; |
||
575 | begin |
||
576 | if Assigned(FOnClose) then FOnClose(Self); |
||
577 | end; |
||
578 | |||
579 | procedure TCustomDXPlay.DoDeletePlayer(Player: TDXPlayPlayer); |
||
580 | begin |
||
581 | if Assigned(FOnDeletePlayer) then FOnDeletePlayer(Self, Player) |
||
582 | end; |
||
583 | |||
584 | procedure TCustomDXPlay.DoMessage(From: TDXPlayPlayer; Data: Pointer; DataSize: Integer); |
||
585 | begin |
||
586 | if Assigned(FOnMessage) then FOnMessage(Self, From, Data, DataSize); |
||
587 | end; |
||
588 | |||
589 | procedure TCustomDXPlay.DoOpen; |
||
590 | begin |
||
591 | if Assigned(FOnOpen) then FOnOpen(Self); |
||
592 | end; |
||
593 | |||
594 | procedure TCustomDXPlay.DoSessionLost; |
||
595 | begin |
||
596 | if Assigned(FOnSessionLost) then FOnSessionLost(Self); |
||
597 | end; |
||
598 | |||
599 | procedure TCustomDXPlay.DoSendComplete(MessageID: DWORD; Result: TDXPlaySendCompleteResult; |
||
600 | SendTime: Integer); |
||
601 | begin |
||
602 | if Assigned(FOnSendComplete) then FOnSendComplete(Self, MessageID, Result, SendTime); |
||
603 | end; |
||
604 | |||
605 | function TCustomDXPlay.GetProviders: TStrings; |
||
606 | |||
607 | function EnumProviderCallback(const lpguidSP: TGUID; lpSPName: LPSTR; |
||
608 | dwMajorVersion: DWORD; dwMinorVersion: DWORD; lpContext: Pointer): |
||
609 | BOOL; stdcall; |
||
610 | var |
||
611 | GUID: PGUID; |
||
612 | begin |
||
613 | GUID := New(PGUID); |
||
614 | Move(lpguidSP, GUID^, SizeOf(TGUID)); |
||
615 | TStrings(lpContext).AddObject(lpSPName, TObject(GUID)); |
||
616 | Result := True; |
||
617 | end; |
||
618 | |||
619 | begin |
||
620 | if FProviders=nil then |
||
621 | begin |
||
622 | FProviders := TStringList.Create; |
||
623 | try |
||
624 | DXDirectPlayEnumerateA(@EnumProviderCallback, FProviders); |
||
625 | except |
||
626 | FProviders.Free; FProviders := nil; |
||
627 | raise; |
||
628 | end; |
||
629 | end; |
||
630 | |||
631 | Result := FProviders; |
||
632 | end; |
||
633 | |||
634 | procedure TCustomDXPlay.GetSessions; |
||
635 | |||
636 | function EnumSessionsCallback(const lpThisSD: TDPSessionDesc2; |
||
637 | var lpdwTimeOut: DWORD; dwFlags: DWORD; lpContext: Pointer): BOOL; stdcall; |
||
638 | var |
||
639 | Guid: PGUID; |
||
640 | begin |
||
641 | if dwFlags and DPESC_TIMEDOUT<>0 then |
||
642 | begin |
||
643 | Result := False; |
||
644 | Exit; |
||
645 | end; |
||
646 | |||
647 | Guid := New(PGUID); |
||
648 | Move(lpThisSD.guidInstance, Guid^, SizeOf(TGUID)); |
||
649 | TStrings(lpContext).AddObject(lpThisSD.lpszSessionNameA, TObject(Guid)); |
||
650 | |||
651 | Result := True; |
||
652 | end; |
||
653 | |||
654 | var |
||
655 | dpDesc: TDPSessionDesc2; |
||
656 | hr: HRESULT; |
||
657 | begin |
||
658 | if FDPlay=nil then |
||
659 | raise EDXPlayError.Create(SDXPlayNotConnectedNow); |
||
660 | |||
661 | ClearSessionList; |
||
662 | |||
663 | FillChar(dpDesc, SizeOf(dpDesc), 0); |
||
664 | dpDesc.dwSize := SizeOf(dpDesc); |
||
665 | dpDesc.guidApplication := DXPlayStringToGUID(FGUID); |
||
666 | |||
667 | hr := FDPlay.EnumSessions(dpDesc, 0, @EnumSessionsCallback, FSessions, DPENUMSESSIONS_AVAILABLE); |
||
668 | if hr=DPERR_USERCANCEL then Abort; |
||
669 | if hr<>0 then |
||
670 | raise EDXPlayError.Create(SDXPlaySessionListCannotBeAcquired); |
||
671 | |||
672 | FReadSessioned := True; |
||
673 | end; |
||
674 | |||
675 | function TCustomDXPlay.GetSessionsPty: TStrings; |
||
676 | begin |
||
677 | if not FReadSessioned then GetSessions; |
||
678 | Result := FSessions; |
||
679 | end; |
||
680 | |||
681 | function TCustomDXPlay.GetProviderNameFromGUID(const ProviderGUID: TGUID): string; |
||
682 | var |
||
683 | i: Integer; |
||
684 | begin |
||
685 | for i:=0 to Providers.Count-1 do |
||
686 | if CompareMem(PGUID(Providers.Objects[i]), @ProviderGUID, SizeOf(TGUID)) then |
||
687 | begin |
||
688 | Result := Providers[i]; |
||
689 | Exit; |
||
690 | end; |
||
691 | |||
692 | raise EDXPlayError.Create(SDXPlayProviderSpecifiedGUIDNotFound); |
||
693 | end; |
||
694 | |||
695 | procedure TCustomDXPlay.CreateDPlayWithoutDialog(out DPlay: IDirectPlay4A; const ProviderName: string); |
||
696 | var |
||
697 | i: Integer; |
||
698 | ProviderGUID: TGUID; |
||
699 | addressElements: array[0..15] of TDPCompoundAddressElement; |
||
700 | dwElementCount: Integer; |
||
701 | Lobby1: IDirectPlayLobbyA; |
||
702 | Lobby: IDirectPlayLobby2A; |
||
703 | lpAddress: Pointer; |
||
704 | dwAddressSize: DWORD; |
||
705 | begin |
||
706 | i := Providers.IndexOf(ProviderName); |
||
707 | if i=-1 then |
||
708 | raise EDXPlayError.CreateFmt(SDXPlayProviderNotFound, [ProviderName]); |
||
709 | ProviderGUID := PGUID(Providers.Objects[i])^; |
||
710 | |||
711 | { DirectPlay address making } |
||
712 | if DXDirectPlayLobbyCreateA(PGUID(nil)^, Lobby1, nil, nil, 0)<>0 then |
||
713 | raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]); |
||
714 | Lobby := Lobby1 as IDirectPlayLobby2A; |
||
715 | |||
716 | FillChar(addressElements, SizeOf(addressElements), 0); |
||
717 | dwElementCount := 0; |
||
718 | |||
719 | addressElements[dwElementCount].guidDataType := DPAID_ServiceProvider; |
||
720 | addressElements[dwElementCount].dwDataSize := SizeOf(TGUID); |
||
721 | addressElements[dwElementCount].lpData := @ProviderGUID; |
||
722 | Inc(dwElementCount); |
||
723 | |||
724 | if CompareMem(@ProviderGUID, @DPSPGUID_MODEM, SizeOf(TGUID)) and ModemSetting.Enabled then |
||
725 | begin |
||
726 | { Modem } |
||
727 | if ModemSetting.FModemName<>'' then |
||
728 | begin |
||
729 | addressElements[dwElementCount].guidDataType := DPAID_Modem; |
||
730 | addressElements[dwElementCount].dwDataSize := Length(ModemSetting.FModemName)+1; |
||
731 | addressElements[dwElementCount].lpData := PChar(ModemSetting.FModemName); |
||
732 | Inc(dwElementCount); |
||
733 | end; |
||
734 | |||
735 | if ModemSetting.FPhoneNumber<>'' then |
||
736 | begin |
||
737 | addressElements[dwElementCount].guidDataType := DPAID_Phone; |
||
738 | addressElements[dwElementCount].dwDataSize := Length(ModemSetting.FPhoneNumber)+1; |
||
739 | addressElements[dwElementCount].lpData := PChar(ModemSetting.FPhoneNumber); |
||
740 | Inc(dwElementCount); |
||
741 | end; |
||
742 | end else |
||
743 | if CompareMem(@ProviderGUID, @DPSPGUID_TCPIP, SizeOf(TGUID)) and TCPIPSetting.Enabled then |
||
744 | begin |
||
745 | { TCP/IP } |
||
746 | if TCPIPSetting.FHostName<>'' then |
||
747 | begin |
||
748 | addressElements[dwElementCount].guidDataType := DPAID_INet; |
||
749 | addressElements[dwElementCount].dwDataSize := Length(TCPIPSetting.FHostName)+1; |
||
750 | addressElements[dwElementCount].lpData := PChar(TCPIPSetting.FHostName); |
||
751 | Inc(dwElementCount); |
||
752 | end; |
||
753 | |||
754 | if TCPIPSetting.Port<>0 then |
||
755 | begin |
||
756 | addressElements[dwElementCount].guidDataType := DPAID_INetPort; |
||
757 | addressElements[dwElementCount].dwDataSize := SizeOf(TCPIPSetting.FPort); |
||
758 | addressElements[dwElementCount].lpData := @TCPIPSetting.FPort; |
||
759 | Inc(dwElementCount); |
||
760 | end; |
||
761 | end; |
||
762 | |||
763 | if Lobby.CreateCompoundAddress(addressElements[0], dwElementCount, nil^, dwAddressSize)<>DPERR_BUFFERTOOSMALL then |
||
764 | raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]); |
||
765 | |||
766 | GetMem(lpAddress, dwAddressSize); |
||
767 | try |
||
768 | FillChar(lpAddress^, dwAddressSize, 0); |
||
769 | |||
770 | if Lobby.CreateCompoundAddress(addressElements[0], dwElementCount, lpAddress^, dwAddressSize)<>0 then |
||
771 | raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]); |
||
772 | |||
773 | { DirectPlay initialization } |
||
774 | if CoCreateInstance(CLSID_DirectPlay, nil, CLSCTX_INPROC_SERVER, IID_IDirectPlay4A, DPlay)<>0 then |
||
775 | raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]); |
||
776 | try |
||
777 | { DirectPlay address initialization } |
||
778 | if DPlay.InitializeConnection(lpAddress, 0)<>0 then |
||
779 | raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]); |
||
780 | except |
||
781 | DPlay := nil; |
||
782 | raise; |
||
783 | end; |
||
784 | finally |
||
785 | FreeMem(lpAddress); |
||
786 | end; |
||
787 | end; |
||
788 | |||
789 | procedure TCustomDXPlay.ClearSessionList; |
||
790 | var |
||
791 | i: Integer; |
||
792 | begin |
||
793 | FReadSessioned := False; |
||
794 | for i:=0 to FSessions.Count-1 do |
||
795 | Dispose(PGUID(FSessions.Objects[i])); |
||
796 | FSessions.Clear; |
||
797 | end; |
||
798 | |||
799 | procedure TCustomDXPlay.Open; |
||
800 | var |
||
801 | PlayerName: string; |
||
802 | begin |
||
803 | Close; |
||
804 | try |
||
805 | if not OpenDPlayWithLobby(PlayerName) then |
||
806 | begin |
||
807 | if not OpenDPlayWithoutLobby(PlayerName) then |
||
808 | Abort; |
||
809 | end; |
||
810 | |||
811 | Open_(PlayerName); |
||
812 | except |
||
813 | Close; |
||
814 | raise; |
||
815 | end; |
||
816 | end; |
||
817 | |||
818 | procedure TCustomDXPlay.Open2(NewSession: Boolean; const SessionName, PlayerName: string); |
||
819 | begin |
||
820 | if not OpenDPlayWithoutLobby2(NewSession, ProviderName, SessionName, PlayerName) then |
||
821 | Abort; |
||
822 | |||
823 | Open_(PlayerName); |
||
824 | end; |
||
825 | |||
826 | procedure TCustomDXPlay.Open_(NameS: string); |
||
827 | |||
828 | function EnumPlayersCallback2(TDPID: TDPID; dwPlayerType: DWORD; |
||
829 | const lpName: TDPName; dwFlags: DWORD; lpContext: Pointer): BOOL; |
||
830 | stdcall; |
||
831 | var |
||
832 | Player: TDXPlayPlayer; |
||
833 | begin |
||
834 | Player := TDXPlayPlayer.Create(TCustomDXPlay(lpContext).Players); |
||
835 | Player.FID := TDPID; |
||
836 | Player.FRemotePlayer := True; |
||
837 | |||
838 | with lpName do |
||
839 | begin |
||
840 | if lpszShortNameA<>nil then |
||
841 | Player.FName := lpszShortNameA; |
||
842 | end; |
||
843 | |||
844 | Result := True; |
||
845 | end; |
||
846 | |||
847 | var |
||
848 | Name2: array[0..1023] of Char; |
||
849 | Name: TDPName; |
||
850 | begin |
||
851 | if FOpened then Close; |
||
852 | FOpened := True; |
||
853 | try |
||
854 | { Player making } |
||
855 | StrLCopy(@Name2, PChar(NameS), SizeOf(Name2)); |
||
856 | |||
857 | Name.lpszShortNameA := @Name2; |
||
858 | Name.lpszLongNameA := nil; |
||
859 | |||
860 | FRecvEvent[0] := CreateEvent(nil, False, False, nil); |
||
861 | |||
862 | FLocalPlayer := TDXPlayPlayer.Create(FPlayers); |
||
863 | FLocalPlayer.FName := NameS; |
||
864 | |||
865 | if FDPlay.CreatePlayer(FLocalPlayer.FID, Name, FRecvEvent[0], nil^, 0, 0)<>DP_OK then |
||
866 | raise EDXPlayError.CreateFmt(SCannotOpened, [FSessionName]); |
||
867 | |||
868 | { Player enumeration } |
||
869 | FDPlay.EnumPlayers(PGUID(nil)^, @EnumPlayersCallback2, Self, DPENUMPLAYERS_REMOTE); |
||
870 | |||
871 | FIsHost := FPlayers.Count=1; |
||
872 | |||
873 | FCalledDoOpen := True; DoOpen; |
||
874 | DoAddPlayer(FLocalPlayer); |
||
875 | |||
876 | { Thread start } |
||
877 | FRecvThread := TDXPlayRecvThread.Create(Self); |
||
878 | FRecvThread.Resume; |
||
879 | except |
||
880 | Close; |
||
881 | raise; |
||
882 | end; |
||
883 | end; |
||
884 | |||
885 | procedure TCustomDXPlay.ChangeDPlay; |
||
886 | var |
||
887 | caps: TDPCAPS; |
||
888 | begin |
||
889 | FAsyncSupported := False; |
||
890 | if FDPlay<>nil then |
||
891 | begin |
||
892 | FillChar(caps, SizeOf(caps), 0); |
||
893 | caps.dwSize := SizeOf(caps); |
||
894 | FDPlay.GetCaps(caps, 0); |
||
895 | |||
896 | FAsyncSupported := caps.dwFlags and DPCAPS_ASYNCSUPPORTED<>0; |
||
897 | end; |
||
898 | end; |
||
899 | |||
900 | function TCustomDXPlay.OpenDPlayWithLobby(out Name: string): Boolean; |
||
901 | var |
||
902 | DPlay1: IDirectPlay2; |
||
903 | Lobby: IDirectPlayLobbyA; |
||
904 | dwSize: DWORD; |
||
905 | ConnectionSettings: PDPLConnection; |
||
906 | begin |
||
907 | Result := False; |
||
908 | |||
909 | if DXDirectPlayLobbyCreateA(PGUID(nil)^, Lobby, nil, nil, 0)<>0 then |
||
910 | Exit; |
||
911 | |||
912 | if Lobby.GetConnectionSettings(0, PDPLConnection(nil)^, dwSize)<>DPERR_BUFFERTOOSMALL then |
||
913 | Exit; |
||
914 | |||
915 | GetMem(ConnectionSettings, dwSize); |
||
916 | try |
||
917 | if Lobby.GetConnectionSettings(0, ConnectionSettings^, dwSize)<>0 then |
||
918 | Exit; |
||
919 | |||
920 | with ConnectionSettings^.lpSessionDesc^ do |
||
921 | begin |
||
922 | dwFlags := DPSESSION_MIGRATEHOST or DPSESSION_KEEPALIVE or DPSESSION_DIRECTPLAYPROTOCOL; |
||
923 | dwMaxPlayers := FMaxPlayers; |
||
924 | end; |
||
925 | |||
926 | if Lobby.SetConnectionSettings(0, 0, ConnectionSettings^)<>0 then |
||
927 | Exit; |
||
928 | |||
929 | if Lobby.Connect(0, DPlay1, nil)<>0 then |
||
930 | Exit; |
||
931 | FDPlay := DPlay1 as IDirectPlay4A; |
||
932 | ChangeDPlay; |
||
933 | |||
934 | with ConnectionSettings.lpSessionDesc^ do |
||
935 | begin |
||
936 | if lpszSessionNameA<>nil then |
||
937 | FSessionName := lpszSessionNameA; |
||
938 | end; |
||
939 | |||
940 | with ConnectionSettings.lpPlayerName^ do |
||
941 | begin |
||
942 | if lpszShortNameA<>nil then |
||
943 | Name := lpszShortNameA; |
||
944 | end; |
||
945 | finally |
||
946 | FreeMem(ConnectionSettings); |
||
947 | end; |
||
948 | |||
949 | Result := True; |
||
950 | end; |
||
951 | |||
952 | function TCustomDXPlay.OpenDPlayWithoutLobby(out Name: string): Boolean; |
||
953 | var |
||
954 | Form: TDelphiXDXPlayForm; |
||
955 | begin |
||
956 | Form := TDelphiXDXPlayForm.Create(Application); |
||
957 | try |
||
958 | Form.DXPlay := Self; |
||
959 | Form.ShowModal; |
||
960 | |||
961 | Result := Form.Tag<>0; |
||
962 | |||
963 | FDPlay := Form.DPlay; |
||
964 | ChangeDPlay; |
||
965 | |||
966 | Name := Form.PlayerName; |
||
967 | FProviderName := Form.ProviderName; |
||
968 | FSessionName := Form.SessionName; |
||
969 | finally |
||
970 | Form.Free; |
||
971 | end; |
||
972 | end; |
||
973 | |||
974 | function TCustomDXPlay.OpenDPlayWithoutLobby2(const NewSession: Boolean; |
||
975 | const ProviderName, SessionName, PlayerName: string): Boolean; |
||
976 | var |
||
977 | dpDesc: TDPSessionDesc2; |
||
978 | i: Integer; |
||
979 | hr: HRESULT; |
||
980 | begin |
||
981 | Result := False; |
||
982 | |||
983 | if FDPlay=nil then |
||
984 | raise EDXPlayError.Create(SDXPlayNotConnectedNow); |
||
985 | |||
986 | if SessionName='' then |
||
987 | raise EDXPlayError.Create(SDXPlaySessionNameIsNotSpecified); |
||
988 | |||
989 | if PlayerName='' then |
||
990 | raise EDXPlayError.Create(SDXPlayPlayerNameIsNotSpecified); |
||
991 | |||
992 | if NewSession then |
||
993 | begin |
||
994 | { Session connection } |
||
995 | FillChar(dpDesc, SizeOf(dpDesc), 0); |
||
996 | dpDesc.dwSize := SizeOf(dpDesc); |
||
997 | dpDesc.dwFlags := DPSESSION_MIGRATEHOST or DPSESSION_KEEPALIVE; |
||
998 | dpDesc.lpszSessionNameA := PChar(SessionName); |
||
999 | dpDesc.guidApplication := DXPlayStringToGUID(GUID); |
||
1000 | dpDesc.dwMaxPlayers := MaxPlayers; |
||
1001 | |||
1002 | hr := FDPlay.Open(dpDesc, DPOPEN_CREATE); |
||
1003 | if hr=DPERR_USERCANCEL then Exit; |
||
1004 | if hr<>0 then |
||
1005 | raise EDXPlayError.CreateFmt(SDXPlaySessionCannotOpened, [FSessionName]); |
||
1006 | end else |
||
1007 | begin |
||
1008 | { Session connection } |
||
1009 | { Enum session } |
||
1010 | i := Sessions.IndexOf(SessionName); |
||
1011 | if i=-1 then raise EDXPlayError.CreateFmt(SDXPlaySessionNotFound, [SessionName]); |
||
1012 | |||
1013 | FillChar(dpDesc, SizeOf(dpDesc), 0); |
||
1014 | dpDesc.dwSize := SizeOf(dpDesc); |
||
1015 | dpDesc.guidInstance := PGUID(Sessions.Objects[i])^; |
||
1016 | dpDesc.guidApplication := DXPlayStringToGUID(GUID); |
||
1017 | |||
1018 | hr := FDPlay.Open(dpDesc, DPOPEN_JOIN); |
||
1019 | if hr=DPERR_USERCANCEL then Exit; |
||
1020 | if hr<>0 then |
||
1021 | raise EDXPlayError.CreateFmt(SDXPlaySessionCannotOpened, [FSessionName]); |
||
1022 | end; |
||
1023 | |||
1024 | Result := True; |
||
1025 | |||
1026 | FSessionName := SessionName; |
||
1027 | end; |
||
1028 | |||
1029 | procedure TCustomDXPlay.Close; |
||
1030 | begin |
||
1031 | FOpened := False; |
||
1032 | FReadSessioned := False; |
||
1033 | |||
1034 | try |
||
1035 | if FCalledDoOpen then |
||
1036 | begin |
||
1037 | FCalledDoOpen := False; |
||
1038 | DoClose; |
||
1039 | end; |
||
1040 | finally |
||
1041 | if FDPlay<>nil then |
||
1042 | begin |
||
1043 | if FLocalPlayer<>nil then FDPlay.DestroyPlayer(FLocalPlayer.FID); |
||
1044 | FDPlay.Close; |
||
1045 | end; |
||
1046 | |||
1047 | FProviderName := ''; |
||
1048 | FSessionName := ''; |
||
1049 | FAsyncSupported := False; |
||
1050 | |||
1051 | ClearSessionList; |
||
1052 | |||
1053 | FDPlay := nil; |
||
1054 | ChangeDPlay; |
||
1055 | |||
1056 | if FInThread then |
||
1057 | SetEvent(FRecvEvent[1]) |
||
1058 | else |
||
1059 | FRecvThread.Free; |
||
1060 | |||
1061 | CloseHandle(FRecvEvent[0]); FRecvEvent[0] := 0; |
||
1062 | |||
1063 | FPlayers.Clear; |
||
1064 | |||
1065 | FLocalPlayer := nil; |
||
1066 | end; |
||
1067 | end; |
||
1068 | |||
1069 | procedure TCustomDXPlay.SendMessage(ToID: TDPID; Data: Pointer; DataSize: Integer); |
||
1070 | begin |
||
1071 | if not Opened then Exit; |
||
1072 | |||
1073 | if DataSize<SizeOf(TDPMSG_GENERIC) then |
||
1074 | raise EDXPlayError.Create(SDXPlayMessageIllegal); |
||
1075 | |||
1076 | if ToID=FLocalPlayer.ID then |
||
1077 | begin |
||
1078 | { Message to me } |
||
1079 | DoMessage(FLocalPlayer, Data, DataSize); |
||
1080 | end else |
||
1081 | if FAsync and FAsyncSupported then |
||
1082 | FDPlay.SendEx(FLocalPlayer.ID, ToID, DPSEND_GUARANTEED or DPSEND_ASYNC, Data^, DataSize, 0, 0, nil, nil) |
||
1083 | else |
||
1084 | FDPlay.Send(FLocalPlayer.ID, ToID, DPSEND_GUARANTEED, Data^, DataSize); |
||
1085 | end; |
||
1086 | |||
1087 | function TCustomDXPlay.SendMessageEx(ToID: TDPID; Data: Pointer; DataSize: Integer; |
||
1088 | dwFlags: DWORD): DWORD; |
||
1089 | begin |
||
1090 | if not Opened then Exit; |
||
1091 | |||
1092 | if DataSize<SizeOf(TDPMSG_GENERIC) then |
||
1093 | raise EDXPlayError.Create(SDXPlayMessageIllegal); |
||
1094 | |||
1095 | Result := 0; |
||
1096 | if ToID=FLocalPlayer.ID then |
||
1097 | begin |
||
1098 | { 自分宛のメッセ[ジ } |
||
1099 | DoMessage(FLocalPlayer, Data, DataSize); |
||
1100 | end else |
||
1101 | FDPlay.SendEx(FLocalPlayer.ID, ToID, dwFlags, Data^, DataSize, |
||
1102 | 0, 0, nil, @Result); // 0 以外はサポ[トしないデバイスあるので使わない |
||
1103 | end; |
||
1104 | |||
1105 | procedure TCustomDXPlay.SetGUID(const Value: string); |
||
1106 | begin |
||
1107 | if Value<>FGUID then |
||
1108 | begin |
||
1109 | if Value='' then |
||
1110 | begin |
||
1111 | FGUID := GUIDToString(GUID_NULL); |
||
1112 | end else |
||
1113 | begin |
||
1114 | FGUID := GUIDToString(DXPlayStringToGUID(Value)); |
||
1115 | end; |
||
1116 | end; |
||
1117 | end; |
||
1118 | |||
1119 | procedure TCustomDXPlay.SetModemSetting(Value: TDXPlayModemSetting); |
||
1120 | begin |
||
1121 | FModemSetting.Assign(Value); |
||
1122 | end; |
||
1123 | |||
1124 | procedure TCustomDXPlay.SetProviderName(const Value: string); |
||
1125 | begin |
||
1126 | Close; |
||
1127 | FProviderName := Value; |
||
1128 | if FProviderName='' then Exit; |
||
1129 | try |
||
1130 | CreateDPlayWithoutDialog(FDPlay, Value); |
||
1131 | except |
||
1132 | FProviderName := ''; |
||
1133 | raise; |
||
1134 | end; |
||
1135 | end; |
||
1136 | |||
1137 | procedure TCustomDXPlay.SetTCPIPSetting(Value: TDXPlayTCPIPSetting); |
||
1138 | begin |
||
1139 | FTCPIPSetting.Assign(Value); |
||
1140 | end; |
||
1141 | |||
1142 | initialization |
||
1143 | CoInitialize(nil); |
||
1144 | finalization |
||
1145 | CoUninitialize; |
||
1146 | end. |