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