|
|
来自: http://social.msdn.microsoft.com ... 9-a8c9-2e27eb9ec058
0 g( [* N6 ?* _1 F6 pBy Mukta & ToxicDream
9 G* G' l. k: |$ \2 g- //for delphi 5# d5 Y3 y! `) C% k0 I
- unit MMDevApi_tlb;
, A$ x! p9 T+ {& w5 K/ [; N% P - 5 O$ Z! |: X$ J7 Z
- interface1 Y m0 O) h3 }, M0 @+ C- V/ s- E0 H
- uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL,ComObj;7 F. j/ E# |; U: X' n
- const
- ]* E0 k( | t$ j& P - // TypeLibrary Major and minor versions9 Z* u Q; P) |" u
- % k+ |1 S/ @' I" i/ @
- CLASS_IMMDeviceEnumerator: TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';$ f9 j( x$ A. @% \
- IID_IMMDeviceEnumerator: TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}'; A) Y/ t W! z* D
- IID_IMMDevice: TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}'; A- Q; A# X# _" |3 O% J( Z
- IID_IMMDeviceCollection: TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';
8 }: m+ ^8 j3 ]" ~. t - IID_IAudioEndpointVolume: TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';. E7 f. v8 i* m% f' c$ H9 i
- IID_IAudioMeterInformation : TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';
/ n) u' b( R3 s9 G - IID_IAudioEndpointVolumeCallback: TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';
/ N: Y, b# Y6 x9 b s' A9 ?, m - $ C+ T9 Q. y. J4 ?$ h, [' F
- DEVICE_STATE_ACTIVE = $00000001;
; g+ o5 D% D" [/ j! Q' O; i1 ? - DEVICE_STATE_UNPLUGGED = $00000002;- e; B1 r0 Z& A- G( c
- DEVICE_STATE_NOTPRESENT = $00000004;
6 J6 u8 C2 @! c6 H: y C - DEVICE_STATEMASK_ALL = $00000007;, V! l* x; O% R' |1 e
2 {. D% N( o8 r- type
4 a( G/ d5 S2 }7 b# z0 @$ w - EDataFlow = TOleEnum;
! ?, o& l# }8 f% ?, N - const. }" L" g8 D2 G8 C3 n6 R
- eRender = $00000000;8 M4 u9 u& u5 G A
- eCapture = $00000001;% a6 J/ v4 P4 D9 j5 E5 l9 `
- eAll = $00000002;* [- H1 i7 h, D/ a
- EDataFlow_enum_count = $00000003;1 t1 G$ q) w5 v! Z7 V) o
- : B' g0 X. ?* P& h0 l6 s3 M K
- type
w- W8 a- R" ]! L( S; T% @ - ERole = TOleEnum;. S$ d7 m" q# h# j
- const8 u* K0 `! X& X/ [) o
- eConsole = $00000000;
4 G5 ]0 a3 k: ]. `, l - eMultimedia = $00000001;7 E2 T2 y5 C1 ^
- eCommunications = $00000002;; N o0 c1 X* ^. Y3 {6 h
- ERole_enum_count = $00000003; O9 |3 R# V+ f9 y( {
- * E, p% X2 {, _. Y; U$ i
- type3 W3 b9 @' {0 n! v) D4 A' y% T9 Q9 S
- IAudioEndpointVolumeCallback = interface(IUnknown)2 Q5 O$ ^+ v; u e% L' ?# s/ V( d
- ['{657804FA-D6AD-4496-8A60-352752AF4F89}']0 I' u! T' |/ k5 |8 |' S7 q2 v* s) y
- end;% S3 F% g; B8 J5 A" D+ H" M
9 u5 v9 ?4 z1 _) `3 s1 m; \- IMMAudioEndpointVolume = interface(IUnknown)
8 z {7 K; C& U- V$ o5 m$ K - ['{5CDF2C82-841E-4546-9722-0CF74078229A}']
& Z4 o9 C1 }& `$ g/ l - Function RegisterControlChangeNotify( AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;9 Q0 S7 _& U+ H: P. f
- Function UnregisterControlChangeNotify( AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;9 G: o" L8 s, ]
- Function GetChannelCount(out PInteger): Integer; stdcall;; W6 m/ E" T7 Q/ t
- Function SetMasterVolumeLevel(fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
- z8 i" } M# T( s - Function SetMasterVolumeLevelScalar(fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
: y# N2 K6 {( M - Function GetMasterVolumeLevel(out fLevelDB: double):Integer; stdcall;7 Q" ]6 w; ]# }5 O. Q7 x1 X
- Function GetMasterVolumeLevelScaler(out fLevel: double):Integer; stdcall;
) W8 M% i3 B' J1 i - Function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
( {6 N; C/ i& p; E4 g i - Function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
* O) N5 J3 _" A9 W) o0 U% q4 i - Function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double) : Integer; stdcall;
* j6 C( h6 Y5 {, _ - Function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double) : Integer; stdcall;
& M# j: S0 i& z* r- E - Function SetMute(bMute: Boolean ; pguidEventContext: TGUID) :Integer; stdcall;
- _2 D3 d0 C- k- H# W$ } - Function GetMute(out bMute: Boolean ) :Integer; stdcall;* {; v& c; v ^# K
- Function GetVolumeStepInfo( pnStep: Integer; out pnStepCount: Integer):Integer; stdcall;
2 \7 A: g: g6 o1 H! B - Function VolumeStepUp(pguidEventContext: TGUID) :Integer; stdcall;; Z3 C2 G1 g$ k! G: G- C
- Function VolumeStepDown(pguidEventContext: TGUID) :Integer; stdcall;
, }5 G# |. s" f - Function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;
: |6 N& i$ ~! {& ? - Function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall;
0 F y/ m3 x2 ` - end;! a# E/ s& C4 E& X9 U0 f
- ; Z0 A4 A5 C$ C: |
- { IAudioMeterInformation = interface(IUnknown)/ f4 z; N7 a. K; T+ u+ w& t; K
- ['{C02216F6-8C67-4B5B-9D00-D008E73E0064']
7 \ ]- R+ V o" _. e - end;}- U! F; R6 o0 R' B
- . Q2 x* m+ p. @- I' u! B; h n
- IPropertyStore = interface(IUnknown)7 @+ [! B' w+ l0 A% O# L
- end;( q! |' u+ x* { w1 }
- $ ^. W/ ?7 d0 l% ^" s- D
- type4 I: t1 C7 p8 J: n B
- IMMDevice = interface(IUnknown): ?/ L( k6 C7 y7 B5 b! b6 F- f
- ['{D666063F-1587-4E43-81F1-B948E807363F}']
. b! a. S; k9 L) ^1 }9 c - Function Activate( refId :TGUID;
0 G; g; ]( ^. K O! u - dwClsCtx: DWORD;9 }: Q: g% l: n
- pActivationParams: PInteger ;" y3 D+ b0 u- g9 [5 Z7 Y
- out pEndpointVolume: IMMAudioEndpointVolume): Hresult; stdCall;
& M. @1 v* C5 C7 t% |6 s - Function OpenPropertyStore(stgmAccess: DWORD; out ppProperties :IPropertyStore): Hresult; stdcall;, {) K4 @( U r6 f
- Function GetId(out ppstrId: PLPWSTR ): Hresult; stdcall;( B' T6 k% G+ M: }
- Function GetState(out State :Integer): Hresult; stdcall;
) {$ t' n e2 R9 T - 8 Y/ k0 i/ P" |" A; W( T4 B" V3 [
- end;8 D: e' O- m, \
4 U1 P: L! U+ J& N) g+ G1 H
: s" z. n8 N7 V, J9 a- IMMDeviceCollection = interface(IUnknown)* M+ x7 d6 Z; W
- ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']0 w1 ~6 P% c. Y7 \- u# k# m0 R8 u" N& P
- end;
( z! p3 Y5 o- k% h; X* i4 ] - : k/ @3 S* S9 f3 P8 J
- IMMNotificationClient = interface (IUnknown)( Z, v! Q+ A" H, _. T
- ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']
1 l; C# h! D! v) R1 W' W) l- f - end;( `8 y4 i/ u1 O- J/ j
- % w; y$ F: ~: I* ]7 P
- IMMDeviceEnumerator = interface(IUnknown)& G+ X+ ^; Z" g5 `, Y
- ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']
& j7 y) e# _4 |/ S3 M - Function EnumAudioEndpoints( dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection:IMMDeviceCollection ): Hresult ; stdcall;8 ?# q1 \+ _! J' X% O1 x# O t
- Function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult ; stdcall;4 D& R, m# J" e; i9 j5 A8 L3 s
- Function GetDevice( pwstrId: pointer ; out Dev :IMMDevice) : HResult; stdcall;; a: ]7 p6 T/ x% M' Z2 k
- Function RegisterEndpointNotificationCallback(pClient :IMMNotificationClient) :Hresult; stdcall;8 n# D6 B# Z1 J; q
- end;0 f2 _3 N/ D+ e4 Y$ Q9 N" c* {
- 4 U0 H1 U0 S0 o. U N% j0 A+ C
- implementation, k9 g( S9 \& s
- end.* O* W. Y$ S5 F
`' m* o4 Y# Z! h: V, `- Thanks & Reagrds,2 R/ o: e2 w- e0 [! z! e. \$ L2 C
- Mukta ...
" [/ c/ i5 d% @ \. M
复制代码
% \8 N% a0 \7 Q+ M7 v$ d: G. A- n- it's work in Delphi 7! p8 p* y. F% y1 t* x
- //////////////////////////
, C1 h: @3 c \% X
3 p9 d, Y$ v3 f+ U) w& o1 O- unit MMDevApi;
3 U, J" P( S9 W9 c. [7 i6 o# e: ^3 d7 K - + @% k& n2 s4 r" d0 E1 y
- interface- {. {! {" z7 x: P$ J" @
5 N; |# J7 C0 C* [- uses% R' K/ C& |- T$ g
- Windows, ActiveX, ComObj;
7 E; ~8 P9 ?- U& Q
8 A9 e0 L# i# T+ L( u' G7 {; U- const. X% }- a( {, N
- CLASS_IMMDeviceEnumerator : TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';2 `+ t* c/ \ c6 z3 I7 e- u
- IID_IMMDeviceEnumerator : TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';
9 G0 Q7 K4 v$ H: n - IID_IMMDevice : TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}';
3 X# M* R4 b* r2 a; o! S; K% A# A - IID_IMMDeviceCollection : TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';
2 Z) g7 E4 s1 C* R$ S! T4 V - IID_IAudioEndpointVolume : TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';' i2 u x, X( \. f. y# t" N
- IID_IAudioMeterInformation : TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';
; s' J9 D2 `7 L - IID_IAudioEndpointVolumeCallback : TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';
# K7 N1 Z" g( j- ^8 \4 I* Y
& \" b( S5 Y3 g, b- DEVICE_STATE_ACTIVE = $00000001;
$ V/ u0 k. e. o7 {8 A. O - DEVICE_STATE_UNPLUGGED = $00000002;0 Z4 d. ^5 V4 A3 v9 j
- DEVICE_STATE_NOTPRESENT = $00000004;; f' C3 X: h; C$ C
- DEVICE_STATEMASK_ALL = $00000007;1 n7 O! h3 N# q
- % t* Z6 S/ ]( C( X: J
- type
. z2 ]6 o# h: e! V- }+ K& w - EDataFlow = TOleEnum; p- Z- p/ c9 A: J/ R
- 6 G) L; O! a- y& D2 l' q* P
- const4 l$ S- M' ]" K% x* P
- eRender = $00000000;
$ k) P h4 \% E( {; d5 O% x - eCapture = $00000001;
2 ?3 R' V; M7 X - eAll = $00000002;
9 \5 b5 f/ g- V/ b; ~6 t - EDataFlow_enum_count = $00000003;
8 R! c k8 _0 c) n2 I
+ f5 G3 c3 q+ ]2 ]8 E- type
" P B' g, j5 E; x& I - ERole = TOleEnum;
0 P3 X8 ~/ P% C7 C
! ^) l1 H! Y! k, J0 _# h6 _- const
5 O3 i& m, l6 ]0 r" h - eConsole = $00000000;2 P* m0 Q# R* g! W2 P
- eMultimedia = $00000001;
% B; u/ M8 t" _/ l5 h - eCommunications = $00000002;( y) u0 g5 [3 k8 y( o+ r4 K* b
- ERole_enum_count = $00000003;7 ~' z5 b! N/ D) B
- # v% L. \! R( l+ \& r5 U
- type, m6 j" c- Q4 t" ^' t9 x
- IAudioEndpointVolumeCallback = interface(IUnknown)2 B" h9 c, K; Y8 T1 e- m7 ]
- ['{657804FA-D6AD-4496-8A60-352752AF4F89}']
0 N! H9 D+ A" R5 N+ q g9 ]% o( Z - end;
& Y1 T4 g" y3 X% w' X7 w
- S5 K$ g7 I- R; S! u- IAudioEndpointVolume = interface(IUnknown)
3 S3 m; J' c* L; r! i$ u4 X' g z - ['{5CDF2C82-841E-4546-9722-0CF74078229A}']
v8 D2 C3 G' P. e0 a+ G$ D5 \& R( t - function RegisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
$ { T+ G1 u9 V - function UnregisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;2 v) J" z, ?9 |% n( k6 B
- function GetChannelCount(out PInteger): Integer; stdcall;
1 i6 q0 V6 z# S/ ~5 @1 n0 R - function SetMasterVolumeLevel(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;0 O9 C3 h& P: w o
- function SetMasterVolumeLevelScalar(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;
& }. O" R, a. a+ ^ S0 P - function GetMasterVolumeLevel(out fLevelDB: single): Integer; stdcall;
( v3 b q, q) J1 ?5 s$ [ - function GetMasterVolumeLevelScaler(out fLevelDB: single): Integer; stdcall;- W3 X! g% z* H5 h! K) Z; n" Q e b0 i
- function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;
2 w. n" T" \/ Z, ~& E7 R- c& G - function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;. N$ X3 B- W& o& ~6 u2 o
- function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double): Integer; stdcall;) p3 R4 ^1 R# e6 Q8 S( l
- function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double): Integer; stdcall;: g6 j* W4 m, z
- function SetMute(bMute: Boolean; pguidEventContext: PGUID): Integer; stdcall;, F, f. {$ w) R! Q& f
- function GetMute(out bMute: Boolean): Integer; stdcall;
: }# v0 G, v: B. K - function GetVolumeStepInfo(pnStep: Integer; out pnStepCount: Integer): Integer; stdcall;& ^7 ?8 W, s0 R8 p0 z# a% a, w
- function VolumeStepUp(pguidEventContext: PGUID): Integer; stdcall;$ O, @' O0 a- S# { m# s [
- function VolumeStepDown(pguidEventContext: PGUID): Integer; stdcall;
8 t- E# H- M. y7 h, o - function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;
6 P# L* B4 s" j; D - function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall;! R9 e( l% P& v* C) ~* v4 ^: l
- end;
. M4 t' F" M: s7 W
( ~2 S+ R" I! d2 L$ G7 d0 S# d4 D# N- IAudioMeterInformation = interface(IUnknown)
5 {0 B: L# |. C* A - ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}']1 W% J _& i4 s0 D& {% Z
- end;# n; O" B I h+ b2 V
- : T/ k- ]) ~6 w8 \
- IPropertyStore = interface(IUnknown)
* u% K4 U3 p6 ], R- D3 ^$ M - end;
! V0 o1 m' U# F* T! A - 6 F, |; |" F( z, q; F
- IMMDevice = interface(IUnknown)' Z0 E. C: e8 v, x: f5 [
- ['{D666063F-1587-4E43-81F1-B948E807363F}']
0 _; ]! |0 K% q* F9 c6 X2 K/ L - function Activate(const refId: TGUID;
6 W; r0 B( o1 d% {1 W - dwClsCtx: DWORD;4 F1 Y) j1 _2 C: y" R1 o6 b2 ]$ F
- pActivationParams: PInteger;) x0 C2 n3 q) f
- out pEndpointVolume: IAudioEndpointVolume): Hresult; stdCall;
' h$ ? l @; ?; P; D* J- Q( v% F - function OpenPropertyStore(stgmAccess: DWORD; out ppProperties: IPropertyStore): Hresult; stdcall;
0 {9 k, j2 c1 o. q - function GetId(out ppstrId: PLPWSTR): Hresult; stdcall;& {0 C5 J _6 Y8 y& c! b
- function GetState(out State: Integer): Hresult; stdcall;
' s% Q9 P0 f9 l+ c - end;5 e$ @1 Q% t1 U
- , Z( z# s& p/ r/ c% v+ ?6 T
$ Z0 b& H. ^8 u$ I+ M1 r- IMMDeviceCollection = interface(IUnknown)
4 D, L4 I- `$ u$ W( i - ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']
" ~8 w% G, r1 q - end;" f, @+ F2 Y) l3 z/ k ?3 J' ^
- 0 V! G$ ?9 |8 r) Z6 X
- IMMNotificationClient = interface(IUnknown)9 G. D1 {" P1 P* [% o4 l
- ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']
. _3 V! S( W! W1 {5 T" p. } - end;2 B3 j/ M& z3 K c$ h; x4 a% D
+ h% X% t6 c& V6 J- IMMDeviceEnumerator = interface(IUnknown)% ?4 E# p. H( j" G$ `/ g* D, P
- ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']7 \" f3 s7 I1 n7 L2 ]
- function EnumAudioEndpoints(dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection: IMMDeviceCollection): Hresult; stdcall;7 @' x8 w, u; g0 @2 p& ]
- function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult; stdcall;
# e, a6 `, Z- Y7 v! K - function GetDevice(pwstrId: pointer; out Dev: IMMDevice): HResult; stdcall;
/ m2 Q9 w3 {& _/ P5 X9 ^) R6 R9 N - function RegisterEndpointNotificationCallback(pClient: IMMNotificationClient): Hresult; stdcall;
0 l; Y! r) m# g0 }* t2 Z# F' F - end;
' A! ] w% n4 S+ @+ X# }: f2 K - - r& [5 R' C. \
- implementation
; M/ V; o# `2 ^
9 g8 ]& q& b7 |( c& K- end.! o* R( r* v8 _
8 R( s, K. \$ r9 L- r- ///////////////////////! o! X5 p" {1 m
- simple sample :)8 p. d0 c4 f/ d
- ///////////////////////
) K5 u* z3 I3 {; t* J& O, c: V
% i" \0 T" ^- x& k! `3 _- //...... other code8 A" }) L& o- t3 I2 Y
- k( O% F& L# K8 n- uses ... ActiveX, MMDevApi, ...;& M) x" f9 s+ {$ G. G8 I" ^. B; l& u& H
- ' `. z. j$ |; e0 }
- //...... other code
t: }( s; x$ J5 T( P1 f" ?
5 K7 j1 z4 [' c* b R8 h. L9 Y- var
1 u( z8 X6 N- ]6 M - endpointVolume: IAudioEndpointVolume = nil;
# V9 X6 k. ^, s7 N) s
+ p' V8 s" q1 {% g- procedure TForm1.FormCreate(Sender: TObject);
0 q- J% ]: z9 w0 e' h( q* e- t - var: p7 ?7 D n2 C7 w& k
- deviceEnumerator: IMMDeviceEnumerator;
9 I9 e" j! A5 \. i" } - defaultDevice: IMMDevice;, o- a [7 `( l& m- \9 u
- begin) p' a% E* O8 ^5 u
- CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, deviceEnumerator);
- Y2 k) i4 m3 |5 l" G - deviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, defaultDevice);: i: T# J: f# T% L3 O
- defaultDevice.Activate(IID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, nil, endpointVolume);
; U! e% {4 R8 |$ c1 q8 @ - end;
% C" a4 m- l& s e# |" s5 x
3 m3 l6 f# x8 C9 L( l! {- procedure TForm1.Button1Click(Sender: TObject);
6 S7 R7 V. _% z: B1 |. f - var
) X) |% r9 Z8 J+ u6 T& D - VolumeLevel: Single;% E/ T6 m; h4 j0 a! E
- begin9 X0 o: k+ Z# ^ R
- if endpointVolume = nil then Exit;
. O b1 U) O: _/ m* m - VolumeLevel := 0.50;
5 ^& B2 `3 v: e3 p/ l" g$ J' ^ - endpointVolume.SetMasterVolumeLevelScalar(VolumeLevel, nil);
9 k5 p% E$ O/ _: O' n! f2 ~) R: x - Caption := Format('%1.8f', [VolumeLevel])
1 w5 ~3 R& _5 E+ i4 `8 H - end;
# l# y0 R5 H5 s3 z$ M$ b& _5 Y- t
$ v$ R* M8 s! m4 |9 T- /////////////////////////////////////
; V- ~+ w: q2 x7 L2 V; U1 s6 a - 7 O9 `3 V: H' d( q- i. J. |
- // with best regards ToxicDream
8 M+ C1 c/ F# {- x+ s
复制代码 |
|