|
|
来自: http://social.msdn.microsoft.com ... 9-a8c9-2e27eb9ec0587 y2 a+ t% k. f& x2 Y8 D
By Mukta & ToxicDream
7 ]: e) }6 t2 S) f- //for delphi 5
& B- _" F9 m7 d, a' Z - unit MMDevApi_tlb;
1 M3 M( c: ?# N, ~ - m- Z3 P0 m' v" v* h, Y
- interface$ h6 i5 q. H/ E. J4 H
- uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL,ComObj;
; j6 H7 [0 O4 O* t( |! b9 O - const
8 r, {. x+ G4 E/ L. P - // TypeLibrary Major and minor versions) X5 V8 m! [- K/ |6 |9 c6 k3 ~
- & W" R7 h) v8 [4 C# b, E- v- v9 q! C
- CLASS_IMMDeviceEnumerator: TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';
( e7 W; [7 d( E/ I - IID_IMMDeviceEnumerator: TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';
1 q3 n( ?% f( Y - IID_IMMDevice: TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}';: d5 s8 D: Y- A3 y9 K+ o2 y9 V9 `
- IID_IMMDeviceCollection: TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';
4 j3 q& E# B1 }0 ^ - IID_IAudioEndpointVolume: TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';
" W0 r( r9 A4 |3 g7 U m% f( G - IID_IAudioMeterInformation : TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';
5 R; c$ b- U! k% r8 K/ q$ d - IID_IAudioEndpointVolumeCallback: TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';( {1 S: q- f {, o& b( Z5 M
0 {. V9 g& p+ i; d+ u6 a- DEVICE_STATE_ACTIVE = $00000001;
# } Q- F5 F& X5 B; g - DEVICE_STATE_UNPLUGGED = $00000002; I) Z/ w8 l5 t+ u1 @4 p8 @3 R
- DEVICE_STATE_NOTPRESENT = $00000004;
# Z* m) l0 Y q - DEVICE_STATEMASK_ALL = $00000007;
3 _1 a7 t) _3 A! [ - % C/ z. C- ~* _
- type; R# w3 O: u0 P, y' l
- EDataFlow = TOleEnum;' ?" o& G8 Q9 \. a G- F6 u5 Z' C8 W
- const
7 v. P( V; L$ E6 t. u D' O - eRender = $00000000;
% X, Z: T1 O/ d& J1 { - eCapture = $00000001;) C! b4 s+ f# `& U: y+ B( {8 Z: s
- eAll = $00000002;' }) ~; W2 s; h/ D# }
- EDataFlow_enum_count = $00000003;
l1 w' g6 Z n
6 D( c' @4 a$ G- type
/ v$ P' N' q0 g - ERole = TOleEnum;$ K: L8 v8 n$ u. I' D) h
- const( s5 D( {9 B6 X- b" E
- eConsole = $00000000;
5 d; X" u# Z0 |; s4 _9 S1 E3 R - eMultimedia = $00000001;
# T3 D, h" t# R" U' f, N" q - eCommunications = $00000002;
9 i! ?. \' v, S( E - ERole_enum_count = $00000003;" t4 r: D4 s8 W
7 s( ~: W& J2 y2 A/ s- type
) [, x5 A0 y7 V2 G" d4 x; U0 ^$ f - IAudioEndpointVolumeCallback = interface(IUnknown); R# C& Z* }/ i# O6 ]) ?- L. t
- ['{657804FA-D6AD-4496-8A60-352752AF4F89}']. W7 _6 G6 N x" [/ V
- end;
! t9 Z0 R( I- \; @2 p) o" |- S
. N5 M( y5 Q( v$ T- IMMAudioEndpointVolume = interface(IUnknown); m/ o5 ~4 l: x* N
- ['{5CDF2C82-841E-4546-9722-0CF74078229A}']1 }: X. X8 r) e4 M3 i$ T
- Function RegisterControlChangeNotify( AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
% e2 m4 {2 \: { - Function UnregisterControlChangeNotify( AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
! ^- a1 Q" ~; M - Function GetChannelCount(out PInteger): Integer; stdcall;4 o- \7 H1 B4 f! @' ~
- Function SetMasterVolumeLevel(fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
, K: r4 [+ q8 o; ~) W' T! K - Function SetMasterVolumeLevelScalar(fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
* Q" `. _3 q) Z5 V+ }% `$ j - Function GetMasterVolumeLevel(out fLevelDB: double):Integer; stdcall;! j+ g. r$ g& v) {! u9 i
- Function GetMasterVolumeLevelScaler(out fLevel: double):Integer; stdcall;9 v1 S- Y( k+ g6 _
- Function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall; k9 L1 m, {* E l
- Function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;$ F+ E/ a, P6 V. P
- Function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double) : Integer; stdcall;* i5 G' ~& F8 D4 U$ W
- Function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double) : Integer; stdcall;- V( [4 i/ t ]
- Function SetMute(bMute: Boolean ; pguidEventContext: TGUID) :Integer; stdcall;6 `+ [1 A I# |" j
- Function GetMute(out bMute: Boolean ) :Integer; stdcall;! c/ y# p7 C3 b1 {
- Function GetVolumeStepInfo( pnStep: Integer; out pnStepCount: Integer):Integer; stdcall;
4 H7 f0 o1 p' u* c$ Y. }' r - Function VolumeStepUp(pguidEventContext: TGUID) :Integer; stdcall;
4 B4 K3 c$ u6 P+ y/ d4 C/ M - Function VolumeStepDown(pguidEventContext: TGUID) :Integer; stdcall;8 ?; T) R- \9 d% P0 w
- Function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;
* @2 n8 G9 F! `. C# p& m - Function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall;
+ e& R9 ?, F" j. b% |) ?( G4 w - end;
5 `: b' k9 `. }
/ u& R: j J3 f% z- { IAudioMeterInformation = interface(IUnknown)
2 ~+ ]4 r. g' w; j1 @ - ['{C02216F6-8C67-4B5B-9D00-D008E73E0064']% U# D; i" {! s+ i. j
- end;}# L. T/ ]! P2 I( {
- . ^' {: v% l) M* g
- IPropertyStore = interface(IUnknown)
5 `) i3 \6 R9 }, ]- b1 q5 Q - end;5 D$ C( @- |0 q: O" Y
- ) P' }+ c6 v, k1 i
- type1 @# K. _, [+ j" i& k
- IMMDevice = interface(IUnknown)
; Y6 N8 m. ^0 h2 [ - ['{D666063F-1587-4E43-81F1-B948E807363F}']
: o3 N# T, M9 [& z/ ] - Function Activate( refId :TGUID;, ?. o1 F% ]' m9 R
- dwClsCtx: DWORD;: e E- A: V! n3 p. u
- pActivationParams: PInteger ;
9 y f% M& b, E$ ^ - out pEndpointVolume: IMMAudioEndpointVolume): Hresult; stdCall;
* f8 o; a0 Z6 I/ i2 Z. L% Z - Function OpenPropertyStore(stgmAccess: DWORD; out ppProperties :IPropertyStore): Hresult; stdcall;
Y* Y, X0 ^. Y* m/ r. j) N - Function GetId(out ppstrId: PLPWSTR ): Hresult; stdcall;
* v# l0 U. K! j* z: b - Function GetState(out State :Integer): Hresult; stdcall;5 D3 |# e n1 D5 V# y) b6 s( Q
- # A# [) g! y; X( W+ n5 R
- end;" F8 E# @- Z- w) A. i
- b1 l1 b d! |. N# u6 m- Z2 W( G
) J! |2 M _+ c- IMMDeviceCollection = interface(IUnknown)
3 U$ r0 x$ t2 ~% O4 E1 S6 K( s) W$ T - ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']% F* k0 b+ c+ n: Y! [( T, d
- end;3 m/ d+ P. i5 E3 ~
- # g. g! w9 H ~9 c, h4 B/ t
- IMMNotificationClient = interface (IUnknown)
: t3 p l, }5 n y2 I6 D - ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']+ m7 Z7 \" h4 z; I- R4 U9 ^
- end;) H" m8 r2 U* S5 F' F* E- E
- ! @6 H! }) a1 T w+ P
- IMMDeviceEnumerator = interface(IUnknown)% I0 _1 X2 x0 r2 f
- ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']' i; y5 ?8 r( | E% U
- Function EnumAudioEndpoints( dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection:IMMDeviceCollection ): Hresult ; stdcall;
3 P( q7 o n& [0 ~1 [, R9 C) E - Function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult ; stdcall;
^& p1 J1 r _; Z9 R! k8 w - Function GetDevice( pwstrId: pointer ; out Dev :IMMDevice) : HResult; stdcall;8 @9 x+ Q( ~4 q0 y( g. u# Y" h' Q
- Function RegisterEndpointNotificationCallback(pClient :IMMNotificationClient) :Hresult; stdcall;$ e8 T4 S! s5 s/ }; Y
- end;
4 ~- B- q" Z @! h0 P+ b4 c }. I - ( ?) p6 g; d* f, R4 ]8 \( V8 B! g
- implementation% }0 w5 l, v) r2 a, K
- end.4 P- g* v- m7 ~ W
1 g% i" ]" v0 w% X. J- Thanks & Reagrds,1 N+ I( r7 s) ^4 B- m5 }: A
- Mukta ...
& m+ I- ?! Q: N1 G+ A
复制代码- ) K. Z7 U6 V" U1 l! f: x
- it's work in Delphi 7
- W* j9 e2 @/ { - //////////////////////////9 q4 E) R; G# N% m9 H1 p
- 2 U% d5 X7 k5 n9 W! o4 B
- unit MMDevApi;
7 l- G' z) U* M' k- k N - & A% c* T8 I% D+ D, ^- p
- interface
6 {0 u# r4 t' _ - 8 \) Q0 w X3 t5 N L5 |% g' O
- uses
) N, R! G; |1 c# \0 X - Windows, ActiveX, ComObj;
* N6 J# F5 `8 \+ `1 X2 L) K - 6 W( C7 a1 s# i1 @* _
- const
4 |' `# }- z; C) h) Y9 z8 | - CLASS_IMMDeviceEnumerator : TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';5 [0 W8 j$ D! m+ U, t
- IID_IMMDeviceEnumerator : TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';
7 w/ g% K( l: j1 _/ k1 j. k7 G - IID_IMMDevice : TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}';
( c" K5 r" Y7 ^+ d4 l% ?- Y - IID_IMMDeviceCollection : TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';1 }3 H ~5 }( }6 r
- IID_IAudioEndpointVolume : TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';9 f+ u$ k0 P2 [0 l- w1 v2 t
- IID_IAudioMeterInformation : TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';
* T) V$ l' q6 `# d: Y( _ - IID_IAudioEndpointVolumeCallback : TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';+ ]) m& d0 A; @$ D" X4 O
& ^ k, p& m! _- DEVICE_STATE_ACTIVE = $00000001;5 @7 I2 F, Y, R! P8 ]/ l
- DEVICE_STATE_UNPLUGGED = $00000002;
3 G& K" C9 r* w" e - DEVICE_STATE_NOTPRESENT = $00000004;
+ o/ t+ x4 D" d k" k8 b0 S# i - DEVICE_STATEMASK_ALL = $00000007;7 }" `8 l( x; q3 d* R- C3 w
- ' f0 P/ S: \; R& k5 [" H/ i
- type" x! Q$ a; q; M2 S
- EDataFlow = TOleEnum;4 Y* d0 X( s; j. _
7 R2 p! H$ Z a% I! n1 W- const
5 x7 S0 n% t7 T* g - eRender = $00000000;: I* @ I% m$ y+ U' @1 t
- eCapture = $00000001;* Y; w) w) [0 S2 n% @
- eAll = $00000002;* i& x8 b0 R4 c1 \) Y
- EDataFlow_enum_count = $00000003;. w2 H" L8 O- Y- a4 Y- f
3 R/ E; M: h) W' V- type5 U! s' v0 G2 s2 V, H
- ERole = TOleEnum;
& g4 v' w; w) \+ V/ |( R
! w( q1 C# c C$ m8 s1 c( ^- const% E! `4 g0 s/ n* k. o
- eConsole = $00000000;( s3 P+ r4 f3 n9 X0 y. [
- eMultimedia = $00000001;
4 y! }6 `. H; @* n0 ?( c - eCommunications = $00000002;
$ @$ d2 Y# K! ]; x# `- A. O - ERole_enum_count = $00000003;* c1 Z9 Q% ], m6 D* l
- 4 i( S! V7 Y- |- Y3 o* W2 [. g( `
- type
3 U# O! } h! g7 e2 s0 y3 t3 c - IAudioEndpointVolumeCallback = interface(IUnknown): a! ~. ^3 h4 q( ]' U- }) G. Z
- ['{657804FA-D6AD-4496-8A60-352752AF4F89}']
/ C I, _) r2 g" e9 B; _ - end;
. m- @5 ]" t* e1 R. @# ^! |8 L& r
9 ^+ K/ M; @( l! C- IAudioEndpointVolume = interface(IUnknown)
4 K% k! W( i' h - ['{5CDF2C82-841E-4546-9722-0CF74078229A}']
: u n9 M/ L" U - function RegisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
1 R v8 Y" w: L' C7 D - function UnregisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
9 P0 G0 i/ p$ c2 u - function GetChannelCount(out PInteger): Integer; stdcall;
0 f* I/ Z8 U- _3 g - function SetMasterVolumeLevel(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;9 p& {: m0 k T( x- I' ]
- function SetMasterVolumeLevelScalar(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;5 p- W. t; h2 N% Q9 z
- function GetMasterVolumeLevel(out fLevelDB: single): Integer; stdcall;: ~# ^6 C6 [- z5 \
- function GetMasterVolumeLevelScaler(out fLevelDB: single): Integer; stdcall; h" L, `! Q7 y V5 x' C
- function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;
' B. R c1 e% P7 Z - function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;
! s; [2 D; X; n8 |) u - function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double): Integer; stdcall;
?4 Z/ W) n. W" C% v# l6 ~ - function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double): Integer; stdcall;7 y" J. P/ Z) M# t& f
- function SetMute(bMute: Boolean; pguidEventContext: PGUID): Integer; stdcall;
! g D' h0 a2 ]/ \' _ - function GetMute(out bMute: Boolean): Integer; stdcall;
$ K4 J4 o+ d0 u$ c& m - function GetVolumeStepInfo(pnStep: Integer; out pnStepCount: Integer): Integer; stdcall;
4 G* I; r% H& e# ^! x - function VolumeStepUp(pguidEventContext: PGUID): Integer; stdcall;' C) t# Y4 N/ ]! q0 q
- function VolumeStepDown(pguidEventContext: PGUID): Integer; stdcall;
7 X. I3 ?5 W4 n4 R3 s - function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;& a+ C1 z5 j$ Z {: n
- function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall;2 Y% b5 Q3 g4 [& ?9 U; P: S
- end;
c' |1 Y7 m% \' \' u - ' L% F% Y% n+ n# i8 h* l% H4 z- V
- IAudioMeterInformation = interface(IUnknown)
, [2 H4 x2 t. c; h1 C0 Q5 m - ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}']0 p( \* g( L% P, m0 ^) X3 i
- end;/ `* w/ q p; t5 P4 f" b2 w8 g
- 4 u! M; A3 J$ D! Q7 k/ U
- IPropertyStore = interface(IUnknown)* B# _- Z$ p( }" B( W, w2 w
- end;
: \& O; y h$ a - 7 Q) d9 j9 \$ p
- IMMDevice = interface(IUnknown)
+ U5 _$ k {; d% Z& Z - ['{D666063F-1587-4E43-81F1-B948E807363F}']- R$ c: f. D5 u
- function Activate(const refId: TGUID;8 W( W( k6 E& }& d7 g
- dwClsCtx: DWORD;" M+ [$ K' D% [$ z* S9 t
- pActivationParams: PInteger;
' `& y! E& l" A; B N% c* W8 A - out pEndpointVolume: IAudioEndpointVolume): Hresult; stdCall;
5 ~' g& Q3 U, v. w - function OpenPropertyStore(stgmAccess: DWORD; out ppProperties: IPropertyStore): Hresult; stdcall;
& X5 d2 `$ |. X8 z, x6 W - function GetId(out ppstrId: PLPWSTR): Hresult; stdcall;/ K) U: }- K& o; ^1 F
- function GetState(out State: Integer): Hresult; stdcall;8 s- j9 |& e/ @
- end;" I! H7 P. E" ]. `2 v7 X3 D- Z
3 z; L% f4 A$ s+ B, V+ Z- 5 k$ ~2 y$ U$ I. y5 y0 G
- IMMDeviceCollection = interface(IUnknown)% Q' k0 ^5 A8 Y1 _! S. o
- ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']
$ b1 f: e7 B+ d% {& q; P+ v - end;
) B/ C- T2 n( j
( g4 z: B0 d% Q- IMMNotificationClient = interface(IUnknown)
, x9 m U/ j; E1 d, K9 n6 l - ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']/ b3 ^. R# l* O2 X( e
- end;) |: P3 g- @; r" V9 H) v! \- l
0 B9 Y5 b8 r0 ~$ V, R- IMMDeviceEnumerator = interface(IUnknown)
* s( _5 p1 R6 {) I- A. q9 ~+ X - ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']4 ^/ q0 S8 N3 l% ]; S
- function EnumAudioEndpoints(dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection: IMMDeviceCollection): Hresult; stdcall;: |* S3 I+ }8 H
- function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult; stdcall;
" ~9 ]) k: @: w U* i9 H9 w - function GetDevice(pwstrId: pointer; out Dev: IMMDevice): HResult; stdcall;
1 N+ @5 A% a* w; o. j) W - function RegisterEndpointNotificationCallback(pClient: IMMNotificationClient): Hresult; stdcall;
* i1 ~4 W/ c6 W9 i - end;
: S1 O% y0 S" U* K" ^8 M" K - - J6 Z' p/ e& n4 `/ u/ d. M! D
- implementation3 i/ E; H# i. ?( _
- 9 g/ U8 a1 T) s- L. r! w. A3 ~
- end.
3 B. {; E+ e, A: g; ~ - * t: D1 W; a- H: V! n
- ///////////////////////6 S# v, N# u3 y; V' L& T z
- simple sample :)) C) K! G& d- R# u' ] e, i
- ///////////////////////$ N3 n( Q- e7 w+ w. n. V7 N
- * \2 s5 Q! X% |7 Y4 |
- //...... other code
3 L7 g# r, ?6 n, j: O$ m: w
% r, T5 S( i) q2 l- uses ... ActiveX, MMDevApi, ...; P8 ^8 ?/ N" B" J+ X2 i! Q" G8 `1 q
/ H2 o6 g3 ~! C0 {- //...... other code
# q/ L) e3 C' T* q' i - % h" k, E. F" p' r5 S
- var+ m$ Q/ A$ q1 k9 w3 E
- endpointVolume: IAudioEndpointVolume = nil;
2 t5 Z$ S+ B) o; m5 M! v9 K/ Y1 H - & q5 E$ b ~8 K5 d# N1 W3 ]
- procedure TForm1.FormCreate(Sender: TObject);
7 }& X+ D- H4 W- b( I; S4 a - var
, f+ B% q2 v" F# | - deviceEnumerator: IMMDeviceEnumerator;
; F% b7 { R! G5 V; o6 J% ^5 L - defaultDevice: IMMDevice;! b9 J, Y0 \% W: f! `
- begin
1 i6 ^0 W' i% G# L - CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, deviceEnumerator);
# Y! d; }, e* P4 M1 P2 l: v' |8 e/ ~ - deviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, defaultDevice);
9 D$ `! ~2 D. b- \ - defaultDevice.Activate(IID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, nil, endpointVolume);
4 d7 L4 m# W, t6 I - end;* Q" S2 q' Q! N3 d1 V
- 9 G7 ]" ?; k V& U) U5 n4 t. v% A
- procedure TForm1.Button1Click(Sender: TObject);
3 `& U5 o) i: }8 u& e$ ~ u - var
! g1 N! ^0 t+ K - VolumeLevel: Single;
: M( l- y6 d3 P% O - begin
* ]# g5 X, g2 Q) @1 L" j: k - if endpointVolume = nil then Exit;9 Q& q' Y' o5 N h# z4 d7 w ?% s
- VolumeLevel := 0.50;9 V& ^- D5 ]& b3 W! a
- endpointVolume.SetMasterVolumeLevelScalar(VolumeLevel, nil);
s, r- @4 z: {6 L! | - Caption := Format('%1.8f', [VolumeLevel])0 P- F, C9 ?. y) Q2 P- C
- end;
& F, i1 Z. J+ h
: R) D4 j1 S+ B: F7 R3 J$ g" a- /////////////////////////////////////
3 n' i8 [1 ^9 R, V: H - ' u+ b; z% n3 C" q# y
- // with best regards ToxicDream
( O0 J. _# O: W/ v
复制代码 |
|