평상시 동영상을 볼 필요가 있는 경우 ,A Player(Windows95/98/Me/화상&사운드)를 사용하고 있습니다. 여러 가지 시험했습니다만 , 이것이 제일 쓰기 쉽다고 생각합니다. 그리고 , 상황에 따라 ,Windows Media Player 9 시리즈나 ,Real.com - RealOnePlayer is now RealPlayer를 사용하기도 하고 있습니다. 물론 후자의2개는 비정상으로 무겁습니다만.
그것은 그것으로서Delphi로부터TWindowsMediaPlayer를 사용하고 싶어졌습니다. RealPlayer(분)편은 놔 두어 ,Windows Media Player 9 를Delphi로부터 이용하고 싶으면 그런 것입니다.
기본방침으로서는 , 인터넷상의 파일이 아니고 , 로컬에 보존되고 있는 파일을 재생하는 것만을 생각합니다. 이라고 할까 , 실제로 시험해 본 결과 , 네트워크상의 파일을 취급하려면 어쩐지 여러 가지 방해 냄새가 난 것 같았던 것과 그런 일은 본가에 맡기고 녹아라고 하는 근처로부터 , 역산된 방침이기도 합니다.
다음의 링크가 , 참고로 한 사이트입니다만 , 대부분이 「Windows Media Player 7 SDK」을 바탕으로 하고 있습니다. 「9」은 아니고 「7」입니다. 개발 환경은 「9」이 들어가 있으므로 돌이킬 수 없습니다만 , 「7」을 사용하고 있는 경우에서도 , 그대로 샘플 코드를 사용할 수 있을 것입니다. 「9밖에 없는 메소드나 프롭퍼티나 이벤트는 모두 사용하고 있지 않습니다」로부터.
우선 ,Windows Media Player 을 컴퍼넌트로서 사용하기 위해서(때문에) , 컴퍼넌트 팔레트에 표시시킬 필요가 있습니다(라고 생각한다). 현재형은 기본적인 순서로 , 과거형이 되어 있는 것은 혹시 변경해야할 것인가도 모르는 순서입니다.
- Delphi의 메뉴로 「파일(F)>모두 닫는다(L)」를 클릭합니다.
- Delphi의 메뉴로 「컴퍼넌트(C)>ActiveX컨트롤의 혼잡(X)...」을 클릭합니다.
- 「ActiveX의 읽어들이기」라고 하는 화면이 열립니다.
- 「Windows Media Player (Version 1.0)」을 선택했습니다.
- 「인스톨(I)...」을 클릭합니다.
- ※한 번 인스톨 하고 있으므로 「옮겨놓습니까?」라고 (들)물었습니다. 「네」로.
- 「인스톨」이라고 하는 화면이 열립니다. 여기는 그대로 변경하지 않고(「기존의 패키지에 추가」라고 하는 탭으로 , 파일명이 「...¥dclusr.dpk」)에 「OK」을 클릭했습니다.
- 「패키지 - dclusr.dpk」라고 하는 화면이 열렸습니다.
- 「인스톨」버튼을 클릭하고 싶은데 사용 불가가 되어 있으므로 「컴파일」을 클릭했습니다.
- 컴파일 후 , 「인스톨」버튼이 사용 가능하게 되었으므로 클릭했습니다.
- 개 버튼으로 닫으려고 하면(자) , 보존할까 (들)물어졌으므로 , 보존했습니다.
- 「ActiveX」탭에 「TWindowsMediaPlayer」이 추가되었습니다.
그렇다고 하는 것 같은 느끼고로 , 대체로로 인스톨 합니다. 필요없게 되었을 때의 지우는 방법입니다만 , 실은 잘 모릅니다. 다만 , 다음과 같이 하는 것이 올바른 삭제의 이상접근인 방법이라고 생각합니다.
- Delphi의 메뉴로 「파일(F)>모두 닫는다(L)」를 클릭합니다.
- Delphi의 메뉴로 「프로젝트(P)>옵션(O)...」을 클릭합니다.
- 「프로젝트 옵션」이라고 하는 화면이 열립니다.
- 「패키지」탭을 선택해 , 「설계시 패키지」일람으로 「Borland User Components」의 체크를 뗍니다.
- 「OK」을 클릭합니다.
- 「ActiveX」탭으로부터 「TWindowsMediaPlayer」이 없어졌습니다.
이후의 샘플에서는 , 폼에 배치한 「TWindowsMediaPlayer」의 Name 는 「player」이라고 합니다.
다음과 같은 함수를 사용해 , 취득한 값을 표시합니다.
procedure TForm1.ShowMsg(const S: string);
begin
if (Assigned(Memo1)) then
begin
if (S <> '') then Memo1.Lines.Add(S);
if (Memo1.Lines.Count > 100) then Memo1.Lines.Delete(0);
end;
end;
다음과 같은 배열을 사용해 , 취득한 값을 표시합니다.
const
ON_OFF: array[Boolean] of string = ('OFF', 'ON');
OK_NG: array[Boolean] of string = ('NG', 'OK');
procedure TForm1.Button14Click(Sender: TObject);
var
b: Boolean;
s: string;
i: integer;
d: double;
begin
ShowMsg(StringOfChar('-', 20));
s := player.versionInfo;
ShowMsg(s);
b := player.settings.autoStart;
s := Format('자동 재생 = %s', [ON_OFF[b]]);
ShowMsg(s);
i := player.settings.balance;
s := Format('스테레오 밸런스(-100..100) = %d', [i]);
ShowMsg(s);
b := player.settings.enableErrorDialogs;
s := Format('에러 다이얼로그 표시 = %s', [ON_OFF[b]]);
ShowMsg(s);
b := player.settings.mute;
s := Format('뮤트 = %s', [ON_OFF[b]]);
ShowMsg(s);
i := player.settings.playCount;
s := Format('재생 회수 = %d', [i]);
ShowMsg(s);
d := player.settings.rate;
s := Format('재생 속도 = %f', [d]);
ShowMsg(s);
b := player.settings.isAvailable['Rate'];
if (b) then
s := '재생 속도 변경 = 가능'
else
s := '재생 속도 변경 = 불가';
ShowMsg(s);
i := player.settings.volume;
s := Format('음량 = %d', [i]);
ShowMsg(s);
b := player.settings.getMode('loop');
s := Format('루프 재생 모드 = %s', [ON_OFF[b]]);
ShowMsg(s);
b := player.settings.getMode('shuffle');
s := Format('랜덤 재생 모드 = %s', [ON_OFF[b]]);
ShowMsg(s);
ShowMsg(StringOfChar('-', 20));
end;
TWindowsMediaPlayer에서는 , 재생 대상의 파일은 플레이 리스트로 관리되고 있습니다. 플레이 리스트는 , 본가의 플레이어에서는 , 직접 파일을 드롭 하면(자) 「재생 리스트1」같은 성적 매력이 없는 이름의 플레이 리스트가 작성됩니다만 ,Delphi그리고 사용할 때도 마찬가지로 ,player.currentPlaylist 그리고 꺼낼 수 있는 플레이 리스트는 표시를 보는 한 「재생 리스트1」에 해당하는 것 같습니다. 아마 보존하거나 하면(자) 화제가 바뀌겠지요지만.
그리고 , 문제는 , 플레이 리스트에 파일을 추가하는 방법입니다. 왜 문제인가 , 라고 하면(자) , 플레이 리스트에 추가하는 메소드는 , 인수를 ,IWMPMedia 이라고 하는 형태로 받기 때문으로 , 이것을 단순하게 파일 패스로부터 만들어 낼 방법을 잘 모릅니다.
그리고 , 여러가지 검색하거나SDK를 바라보거나 하고 있으면(자) ,player.mediaCollection.add 라고 하는 메소드가 ,IWMPMedia 를 돌려주는 것을 알 수 있었습니다. 그리고 , 다음의 코드는 이것을 이용하고 있다는 것입니다.
본래의 것 player.mediaCollection 은 , 미디어일 추가해 나가 , 저작권자라든지 장르등으로 좁힌 플레이 리스트를 작성하는 메소드가 있으므로 , 이것을 이용해 대량의 미디어로부터 보고 싶은 미디어를 비식과 꺼내 , 그 만큼을 재생한다 , 라고 하는 것 같은 목적으로 사용하지만 같습니다.
그리고 , 훨씬 훗날을 위해서(때문에) , 플레이 리스트에 무엇이 들어가 있을까를 알아 둘 필요가 있으므로 ,ListBox에 추가한 미디어를 표시하고 있습니다.
procedure TForm1.Button17Click(Sender: TObject);
var
i: integer;
Media: IWMPMedia;
begin
if OpenDialog1.Execute then
begin
for i := 0 to OpenDialog1.Files.Count - 1 do
begin
try
Media := player.mediaCollection.add(OpenDialog1.Files[i]);
player.currentPlaylist.appendItem(Media);
ListBox1.Items.Add(Media.name + '=' + Media.sourceURL);
except
;
end;
end;
end;
end;
이하의2개의 「선택한 미디어를...한다」라고 하는 처리로 , 리스트 박스와 플레이 리스트의 대응이 필요하게 됩니다. 그렇다고 할까 이 때문에 리스트 박스에 추가하고 있습니다.
플레이 리스트중의 액티브한 미디어를 변경하는 것도 , 미디어를 삭제하는 것도 , 변함 없이 IWMPMedia 로 지정할 필요가 있습니다. 이 IWMPMedia 를 찾는데 또다시 파일 패스는 사용할 수 없기 때문에(뭐 보통 같은 생각이 들어 왔습니다만), 리스트 박스와의 대응을 하고 있습니다만 , 문제는SDK을 보면(자) , 「상정외의 파일 삭제에도 대응합시다」라고 있습니다. 즉 리스트 박스에는 표시되고 있는데 , 실제의 파일이 어디엔가 행방불명이 되어 있는 상태가 있을 수 있는 , 이라고 하는 것이군요. 여기에서는 생각하고 있지 않습니다.
procedure TForm1.Button18Click(Sender: TObject);
begin
if (ListBox1.ItemIndex = -1) then exit;
player.controls.stop;
Label3.Caption := player.currentMedia.name;
player.controls.currentItem := player.currentPlaylist.Item[ListBox1.ItemIndex];
Label2.Caption := player.currentMedia.name;
player.controls.play;
end;
procedure TForm1.Button15Click(Sender: TObject);
var
Media: IWMPMedia;
begin
if (ListBox1.ItemIndex = -1) then exit;
Media := player.currentPlaylist.Item[ListBox1.ItemIndex];
player.currentPlaylist.removeItem(Media);
ListBox1.DeleteSelected;
end;
이하의1행 처리들은 , 실제의 곳 ,TWindowsMediaPlayer을 폼상에 둔 것만으로 , 표준으로 컴퍼넌트에 표시되고 있는 버튼에 거의 대응하고 있습니다. 즉 , 정말로 이만큼의 처리를 실시하는 버튼을 배치할 필요는 , 코렙폿치도 없을 것이라고 말하는 것입니다.
procedure TForm1.Button6Click(Sender: TObject);
begin
player.controls.next();
end;
procedure TForm1.Button9Click(Sender: TObject);
begin
player.controls.previous();
end;
procedure TForm1.Button8Click(Sender: TObject);
begin
player.controls.play();
end;
procedure TForm1.Button10Click(Sender: TObject);
begin
player.controls.stop();
end;
procedure TForm1.Button7Click(Sender: TObject);
begin
player.controls.pause();
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
player.controls.fastForward();
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
player.controls.fastReverse();
end;
이것은 , 재생중의 미디어가 없으면 의미가 없는 정보입니다. 실제 ,nil체크를 실시하지 않은 채로 , 완전히 파일을 추가하지 않고 이 처리를 실시하면 , 예외가 발생해 버립니다.
procedure TForm1.Button1Click(Sender: TObject);
var
s, s1, s2: string;
d1, d2: double;
begin
ShowMsg(StringOfChar('-', 20));
if (player.currentMedia = nil) then
begin
s := '재생중의 미디어가 없습니다. ';
ShowMsg(s);
end
else
begin
s1 := player.currentMedia.durationString;
s2 := player.controls.currentPositionString;
s := Format('현재 위치 %s / 재생 시간 %s', [s2, s1]);
ShowMsg(s);
d1 := player.currentMedia.duration;
d2 := player.controls.currentPosition;
s := Format('현재 위치 %f 초 / 재생 시간 %f 초', [d2, d1]);
ShowMsg(s);
end;
ShowMsg(StringOfChar('-', 20));
end;
차의 것은 , 컴퍼넌트에 표준으로 붙어 있는 트럭 바로 현재 위치를 변경했을 때 등에 불리는 이벤트(OnPositionChange)입니다. 원래의 위치와 새로운 위치가 건네받아 옵니다. 어떻게 사용하는지 모릅니다만 , 강제적으로 바탕으로 되돌린다든가?
procedure TForm1.playerPositionChange(Sender: TObject; oldPosition,
newPosition: Double);
var
s: string;
begin
ShowMsg(StringOfChar('-', 20));
s := Format('%f 초 -> %f 초로 변경', [oldPosition, newPosition]);
ShowMsg(s);
ShowMsg(StringOfChar('-', 20));
end;
예상외로 길어졌으므로 , 그2에 계속됩니다.