Informações pessoais Informações Pessoais
Ciência e Tecnologia Ciência e Tecnologia
Embarcadero Delphi Delphi
Para Sua Área Profissional Área Profissional

 

Delphi Delphi

Pgina sobre a Linguagem
de programao da Embarcadero

Criando um Tocador de udio com Playlist

03-09-2013


Voc, provavelmente, j desejou criar seu prprio player de udio. E isso no difcil, se usarmos o componente MediaPlayer

Faa o download do programa pronto. Para adicionar msicas Playlist, cique com o boto direito sobre a rea em branco e escolha "Adicionar msica".

do Delphi, presente na paleta System. Ento, mos obra.

Crie um novo projeto e vamos adicionar a ele trs componentes Panel: um ficar alinhado na parte superior do formulrio, outro na lateral esquerda e o terceiro ocupar a rea restante. Mas para que eles se comportem da maneira desejada, vamos ajustar a propriedade Align de cada um deles. Para o Panel que ficar alinhado ao topo, ajuste-a para alTop. Para o que ficar esquerda, mude para alLeft. O outro, ainda no deve ser alterado: faremos isso via cdigo posteriormente. Assim, sua aplicao, por enquanto, tem essa aparncia:


OK, uma aparncia nada agradvel, mas vamos modific-la aos poucos. Clique no Panel1 e vamos alterar sua propriedade Caption para algo que indique o objetivo do programa. Digite, por exemplo, Playlist. Nos panels dois e trs, simplesmente apague o texto dos Captions - eles ficaro vazios.

Agora, da paleta Additional, pegue um componente Splitter e coloque prximo ao Panel2. Este componente ser muito til: ele permitir o redimensionamento do segundo painel quando voc executar seu programa, permitindo o ajuste de sua largura conforme seu gosto.  Sempre que o segundo painel for redimensionado, o terceiro painel ir, tambm, se auto-ajustar ao espao que lhe sobrou. Mas, para que isso ocorra, vamos inserir o seguinte cdigo no evento OnCreate do formulrio:

//Cdigo para o evento OnCreate do form1
procedure TForm1.FormCreate(Sender: TObject);
begin
  Panel3.Align := alClient;

end;

O alinhamento alClient diz ao Panel que ele dever ocupar toda a rea restante do formulrio. Podemos tambm eliminar as bordas dos painis, para que fiquem mais sutis.Para isso, altere a propriedade BevelOuter de cada Panel para bvNone.

Agora, pegue um componente ListBox da paleta Standard e coloque-o no terceiro Panel. Esta ListBox conter os nomes das msicas que sero executadas. Ajuste o componente no centro do Panel e altere sua propriedade Anchors para que akLeft, akTop, akRight e akBottom fiquem como True. Isso permitir que, quando o terceiro panel sofrer um redimensionamento, a Listbox o acompanhe. No entanto, deixe um pouco mais de espao prximo ao rodap da Listbox, pois l iremos adicionar os botes que controlaro a playlist. Eis o que voc deve ter at o momento:


Se voc executar seu aplicativo neste ponto, ver que o redimensionamento com o Splitter j funciona, influenciando nas dimenses dos Panels 2 e 3 e, conseqentemente, na da Listbox.

Vamos adicionar, agora, o nosso componente principal: o MediaPlayer, da paleta System. Coloque-o no Panel1 e altere sua propriedade Visible para False. Ns no desejamos ver os botes deste componente, pois iremos criar nossos prprios botes de comando para nossa playlist - isso nos permitir um controle maior sobre as aes do aplicativo.

Para os botes, usaremos seis SpeedButtons (), da paleta Additional. Coloque-os abaixo da ListBox. interessante alterar a propriedade Name de cada um deles de acordo com a funo que ir exercer. Assim, na ordem, renomeie-os para BtnBack, BtnNext, BtnPlay, BtnPause, BtnStop e BtnSair - eles sero, respectivamente, os botes de voltar, avanar, tocar, pausar e parar as msicas da playlist; o ltimo ir fechar o aplicativo. Devemos tambm colocar pequenas figuras nestes botes. No arquivo zipado disponibilizado para download esto as figuras usadas para cada boto, prontas para voc utilizar. Basta associ-las propriedade Glyph de cada SpeedButton.

Ainda, abaixo da seqncia de botes, coloque uma TrackBar (paleta Win32). Ela ser usada como controle de volume do software. Ajuste a propriedade ThumbLength da TrackBar para 14. Isso deixar o seu "ponteiro" em um tamanho menor, mais discreto. Ajuste tambm a propriedade TickMarks para tmTopLeft. Assim, as marcas indicadoras de posio (os "risquinhos" milimtricos da TrackBar) ficaro na parte superior do componente, e no abaixo dele. Agora, ajuste a propriedade TickStyle para tsManual. Isso eliminar todos os "risquinhos" da TrackBar, deixando apenas os indicadores inicial e final de posio, proporcionando ao  componente um visual mais "limpo". Por fim, altere o valor da propriedade Max para 99. Esse ser o volume mximo que o componente dever atingir. Cabe aqui uma explicao: teoricamente, o volume mximo deveria ser 100 (ou seja, 100% do total obtido), mas por um falha do componente, ao chegar a 100, o volume totalmente zerado - o que no pode acontecer. Por isso, deixe-o com o valor de 99. Essa diferena de 1 ponto no faz diferena ao ouvido humano.
 

De volta paleta Standard, adicione ao formulrio, em qualquer local, um componente PopupMenu. Este um menu especial, daqueles que so acionados quando clicamos em cima de algum objeto com o boto direito do mouse. O que queremos aqui que, ao clicarmos com o boto direito do mouse na Listbox, surja um menu com as opes de adicionar e remover faixas da playlist. Para isso, clique na ListBox e busque a propriedade PopupMenu. Clique na caixa de seleo logo frente e escolha PopupMenu1. Pronto: a ligao entre o nosso menu e a Listbox est feita.
 

Falta adicionar opes ao menu. Para isso, clique duas vezes sobre o componente que voc acabou de colocar no formulrio e digite Adicionar msica e pressione ENTER. Depois, digite Remover faixa e pressione ENTER. Voc ter algo semelhante a isto:


O nosso pequeno menu j tem opes suficientes agora. Mas, bvio, falta codific-las, mas faremos isso depois. Por enquanto, precisamos de mais dois componentes: um Timer (paleta System) e um OpenDialog, da paleta Dialogs.
 

Codificando o aplicativo

Agora que entramos na parte mais trabalhosa. D dois cliques no seu formulrio para entrarmos na Unit1, onde iremos iniciar a codificao. Antes da seo Implementation, vamos declarar algumas variveis que sero necessrias:

Lista : TStringList;
PLAYING : Boolean = FALSE;
Cont : Integer = 0 ;

A varivel Lista, do tipo TStringList, capaz de armazenar uma lista de textos: ideal para guardar nossa playlist, que nada mais do que uma poro de caminhos de pastas e arquivos de udio. O objetivo que a lista sempre carregue e salve um arquivo .TXT (texto simples) contendo os nomes das msicas escolhidas. A varivel PLAYING, do tipo Boolean, permite que o sistema saiba se ainda h msica  em execuo ou no: sempre que se pressionar o boto Play, PLAYING dever ser True (isto , est em execuo); sempre que se pressionar o boto Stop, ela dever ser False. Note que ela j foi declarada e, ao mesmo tempo, iniciada como False, pois o aplicativo no inicia tocando msica de imediato. E, por fim, a varivel Cont, que armazenar qual faixa da varivel Lista est sendo tocada. Isso necessrio para que, ao retomarmos uma msica depois de uma pausa (boto Pause), o player continue executando a mesma msica, ao invs de retornar para a primeira da lista de novo. Note tambm que Cont j foi iniciada com 0 (zero), pois 0 o primeiro item de uma TStringList, 1 o segundo, 2 o terceiro, e assim por diante. Ou seja, ao comear a tocar, inicia-se pela primeira msica da Lista.

Vamos usar a varivel Lista agora: no evento OnCreate do formulrio, aps a linha Panel3.Align := alClient, digite o seguinte:

Lista := TSTringList.Create;

if FileExists(ExtractFilePath(ParamStr(0))+'Lista.txt') then begin
 Lista.LoadFromFile(ExtractFilePath(ParamStr(0))+'Lista.txt');

for i:=0 to Lista.Count-1 do
ListBox1.Items.Add(ExtractFileName(Lista.Strings[i]));
end;

 

Vamos analisar o que fizemos: toda lista de Strings precisa ser criada na memria primeiro para poder ser usada; por isso, usamos TStringList.Create e atribumos essa nova lista varivel j declarada. Depois, verificamos se j existia previamente um arquivo texto com alguma playlist salva anteriormente com a funo FileExists. Se FileExists for True, ento carrega a lista com as msicas atravs da funo LoadFromFile. Note a utilizao de uma funo adicional: ExtractFilePath(ParamStr(0)). Este um meio que se tem de descobrir onde est o executvel do nosso programa. Como desejamos armazenar nosso arquivo texto (Lista.txt) no mesmo local do executvel para facilitar, usamos ParamStr (0), que contm todo o caminho de pastas at o nome do arquivo executvel e, ao mesmo tempo, extramos com ExtractFilePath apenas a informao que nos interessava: o diretrio do executvel.

Por fim, usamos um lao for...do para adicionarmos ao componente ListBox, um a um, todos os arquivos contidos em Lista.txt, mas sem o caminho das pastas, deixando apenas o nome do arquivo listado. O caminho de pastas pode ser retirado usando-se a funo ExtractFileName(), que extrai de uma string apenas a poro que corresponde exatamente o nome do arquivo.

Estes procedimentos acontecem todos no evento OnCreate do form. Vamos codificar agora a opo do menu Popup Adicionar Msica. Em seu evento OnClick, digite este cdigo:

 if OpenDialog1.Execute then begin
  Lista.Add(OpenDialog1.FileName);
  ListBox1.Items.Add(ExtractFileName(OpenDialog1.FileName));
 
end;


O cdigo acima faz com que uma caixa de dilogo "Abrir Arquivo", tpica do Windows, aparea na tela para que o usurio possa escolher qual arquivo deseja adicionar playlist. Com o mtodo Execute, estamos dizendo que, se o usurio escolher um arquivo e clicar no boto abrir, o nome do arquivo ser passado nossa Lista (atravs do mtodo Add()) e tambm playlist que aparece na ListBox (atravs de Items.Add()), mas no sem antes remover todo o caminho de pastas (de novo!) para que possamos exibir apenas o nome da msica.

O menu Popup Remover faixa faz o inverso. Ele pergunta, em primeiro lugar, se desejamos mesmo remover a faixa selecionada. Para isso, usamos Application.Messagebox, que mostra uma caixa de mensagens na tela, tpica do Windows tambm, e que retorna IDYES se o usurio clicar em "Sim", e IDNO se escolher "No":

if application.messagebox (pchar('Remover faixa '+ ListBox1.Items.strings[ListBox1.ItemIndex] + '?'), pchar(Caption),36) = IDYES then begin
 Lista.Delete(ListBox1.ItemIndex);
 ListBox1.DeleteSelected;
 
if Cont > 0 then
  Cont := Cont - 1;
end;


Note que, para sabermos em qual msica o usurio clicou, usamos uma propriedade interessante da ListBox chamada ItemIndex. Ela armazena a posio em que est o texto sobre o qual o mouse clicou. O que precisamos fazer depois pedir que esse item seja removido da lista - alis, de ambas: da lista que armazena todo o caminho de pastas at as msicas e tambm das ListBox. A linha Lista.Delete(ListBox1.ItemIndex) apaga o nome do arquivo que contm o caminho completo e ListBox1.DeleteSelected apaga o item selecionado na ListBox que, teoricamente, o que mais importa para o usurio, pois o item que ele v na tela. O que vem depois um complemento para evitar falhas na execuo da playlist: o nosso contador Cont, que guarda o nmero da msica em execuo, precisa tambm saber que a msica atualmente clicada foi removida e que, em virtude disso, ele deve voltar para a faixa anterior. Foi o que fizemos em Cont := Cont - 1.  Mas note que ele s subtrair 1 do valor de Cont se realmente houver mais msicas na listagem - ou seja, se Cont > 0  pois, se Cont for zero, significa que no h como voltar para a msica anterior: a lista est vazia.
 

Os botes Play, Pause, Stop, Avanar e Voltar

Agora, vamos melhor parte: codificar os botes de Play e Stop. Primeiro, o Play. No seu evento OnClick, coloque isto:

 if PLAYING then MediaPlayer1.Resume

  else begin

   MediaPlayer1.Close;
   MediaPlayer1.FileName := Lista.Strings[Cont];
   ListBox1.Selected[Cont] := True;
   MediaPlayer1.Open;
   MediaPlayer1.Play;
   Timer1.Enabled := True;//habilita timer
 end;

PLAYING := True;

Ao clicar em Play, nosso software precisa verificar se ele dever comear a tocar uma faixa desde o comeo ou se para continuar uma faixa anteriormente pausada. Para isso, testamos nossa varivel PLAYING: se ela for True, indica que a faixa j estava em execuo e, portanto, provavelmente agora estava pausada, devendo continuar a partir do ponto de parada. Isso pode ser feito com o mtodo Resume do MediaPlayer: ele prossegue tocando a msica exatamente a partir do ponto onde ela se encontrava. o que faz a linha  if PLAYING then MediaPlayer1.Resume. Mas se PLAYING no era True, ento no havia msica em execuo, devendo comear uma desde o incio.

Precisamos, ento, mostrar ao player qual a faixa que ele deve tocar, escolhendo a atual da nossa lista atravs de Lista.Strings[Cont]. Lembre-se que Cont guarda qual msica da nossa lista deve ser tocada e, passando Cont como parmetro para nossa Lista atravs da propriedade Strings, pegamos o nome do arquivo a ser executado na seqncia. Isso quer dizer que, se Cont contiver o valor 5, ao fazermos Lista.Strings[Cont], nossa Lista saber que deve pegar a sexta linha e atribuir ao MediaPlayer. o que acontece em MediaPlayer1.FileName := Lista.Strings[Cont].

Adicionalmente, a ListBox deve mostrar qual a faixa selecionada com  ListBox1.Selected[Cont] := True. Essa linha permite isso, usando a mesma varivel Cont para que a ListBox possa indicar qual linha deve estar marcada. O que vem a seguir apenas uma consequencia: o MediaPlayer deve ser aberto com Open e executar a cano com Play. Alm disso, o Timer deve ser habilitado com Timer1.Enabled:=True e nossa varivel PLAYING deve passar para True, indicando ao software que h uma faixa sendo reproduzida.

O boto de Stop mais fcil:

 if PLAYING then begin
  MediaPlayer1.Stop;
  PLAYING := FALSE;
  Timer1.Enabled := False;
 end;

Aqui, se h faixa sendo tocada, o MediaPlayer deve ser parado atravs da funo Stop. Alm disso, PLAYING deve se tornar False e o Timer deve ficar desabilitado, com Timer1.Enabled := False.

E, mais fcil ainda, o boto de pausa:

 MediaPlayer1.Pause;


Aqui, nada de duvidoso: apenas chamamos a funo Pause do componente MediaPlayer. Mas, para os botes de Avanar e Retroceder, as coisas so um pouco diferentes. Para cada vez que clicarmos num deles, a execuo da faixa atual e o timer devero ser parados; o MediaPlayer deve ser fechado, um novo arquivo musical da lista deve ser atribudo a ele em sua propriedade FileName para, ento, ele ser aberto novamente e ter sua funo Play chamada. Como os dois botes precisaro da mesma funcionalidade, melhor criarmos uma procedure separada e depois apenas cham-la em cada um dos eventos OnClick. Para isso, localize o incio dos cdigos da sua Unit e, entre as declaraes Type e Private, acrescente esta:

 procedure MudaFaixa(Valor : Integer);

Isso apenas indica ao Delphi que desejamos criar uma nova procedure. Para cri-la de fato, clique com o cursor do mouse sobre ela e pressione CTRL+SHIFT+C no teclado. Isso far com que o "corpo" da funo seja criado. Nele, digite o seguinte:

if (Valor <> -1) and (Valor <> 1) then exit;

if PLAYING then begin
MediaPlayer1.Stop;
Timer1.Enabled := False;
PLAYING := FALSE;
end;

Cont := Cont + Valor;
MediaPlayer1.Close;


if
(Cont > (ListBox1.Items.Count -1)) then
Cont := 0
else
if
(Cont < 0) then
Cont := (ListBox1.Items.Count -1) ;


MediaPlayer1.FileName := Lista.Strings[Cont];
ListBox1.Selected[Cont]:=true;
MediaPlayer1.Open;
MediaPlayer1.Play;

Timer1.Enabled := True;
PLAYING := True;


Note o uso de uma varivel extra que estamos usando desde que a funo foi declarada, na parte superior da Unit: a varivel Valor. Atravs dela, passaremos um parmetro para a funo que dever ser 1 se desejamos avanar uma msica; -1 se quisermos retroceder uma msica. Qualquer valor diferente de 1 e -1 ser ignorado pela nossa procedure. o que nos diz a primeira linha: if (Valor <> -1) and (Valor <> 1) then exit. Isso significa que se Valor receber algo diferente de 1 ou -1, simplesmente "caia fora", ou seja, no execute o resto da funo.

O prximo bloco de cdigo responsvel por interromper a execuo da faixa sempre que quisermos avanar ou voltar em nossa playlist. Por isso, precisamos parar o MediaPlayer (usando o mtodo Stop), parar o Timer (deixando Enabled em False) e dizer que, naquele instante, a msica que estava sendo reproduzida parou, atravs de PLAYING:=False.

Depois disso, nossa varivel Cont dever "pular" de faixa, adicionando o contedo da varivel Valor, para saber se ela deve buscar a prxima faixa da Lista ou a anterior. nesse ponto que nosso programa usar o 1 ou -1, pois um destes valores estar armazenado em Valor. Alm disso, o MediaPlayer deve ser fechado com o mtodo Close.

Agora, um detalhe importante, para o qual o internauta Flvio Bernardes, que leu este artigo, me chamou a ateno: note que se j estivermos executando a ltima faixa da lista e a procedure receber, novamente, o valor 1, para tentar ir para uma faixa posterior,  o nosso aplicativo ir disparar um erro, j que no h mais faixas. O mesmo acontecer se, estando na primeira faixa, nossa procedure receber de novo o valor -1, como que tentando voltar para uma faixa anterior que no existe.

Para resolver este problema, precisamos fazer o seguinte: se estivermos no final da lista (onde a quantidade total de faixas ser ListBox1.Items.Count-1), deveremos voltar para a primeira faixa (e Cont ser zero de novo, pois a primeira msica est na posio zero). Do mesmo modo, se estivermos na primeira (onde Cont j zero) e tentarmos voltar para uma anterior, devemos, ento, executar a ltima da lista, e Cont dever ser atribudo de ListBox1.Items.Count-1. Observe:

if (Cont > (ListBox1.Items.Count -1)) then
Cont := 0

Portanto, para quando Cont ultrapassar o valor final da lista, Cont dever receber zero de novo, para tocar a primeira faixa. Mas, se Cont receber um nmero menor que zero, ento no h faixas antes da atual e, portanto, dever ir para a ltima da lista:

if (Cont < 0) then
Cont := (ListBox1.Items.Count -1) ;
 

Feito isso, um novo arquivo de udio deve ser atribudo ao MediaPlayer, atravs de sua propriedade FileName, usando o valor atual do contador Cont, que pegar a faixa correta da lista de Strings. o que acontece na linha  MediaPlayer1.FileName := Lista.Strings[Cont]. Mais uma vez, precisamos mostrar qual , ento, a nova msica que est selecionada na ListBox, atravs da linha  ListBox1.Selected [Cont]:=true. Por fim, abre-se o player com a funo Open e inicia-se a reproduo novamente, com a funo Play. Neste momento, o Timer novamente habilitado e PLAYING passa, outra vez, para True.

Com isso, j podemos codificar os botes Avanar e Voltar. No primeiro, coloque o seguinte no seu evento OnClick:

 MudaFaixa(1);

No segundo, coloque isto no evento OnClick:

 MudaFaixa(- 1);

Isso faz com que a funo MudaFaixa() receba o valor 1 para avanar, sabendo que dever ir para a faixa seguinte, e -1 para retroceder, sabendo que dever voltar uma faixa.
 

O Timer do Aplicativo

Vamos codificar o Timer agora. J habilitamos e desabilitamos o Timer diversas vezes em nosso cdigo, mas o que ele far realmente? Eis o que deve ser digitado no evento OnTimer do componente Timer1:

 if MediaPlayer1.Position = MediaPlayer1.Length then begin
  with MediaPlayer1 do begin
   Cont := Cont + 1;
   if Cont > Lista.Count-1 then
    Cont := 0;
  Close ;
   if FileExists(Lista.Strings[Cont]) then begin
     FileName := Lista.Strings[Cont];
     Open ;
     Play;
   end
 else
    Cont := Cont + 1;
  end;
//with MediaPlayer
 end;
//if MediaPlayer

ListBox1.Selected[Cont] := True ;


A primeira linha verifica o andamento da msica do MediaPlayer; se a posio da faixa (Position) for igual a sua largura (Length), ento significa que aquela faixa chegou ao final e o player deve  mudar para a seguinte. Ele faz isso somando 1 ao valor do contador Cont, fechando o MediaPlayer com Close e obtendo o novo nome de arquivo de udio a executar. Abre-se, ento, o novo arquivo (com Open) e inicia-se sua reproduo com o mtodo Play. Note que, aqui, antes de iniciar a nova faixa, recomendvel verificar se o arquivo contido na playlist ainda existe no disco do computador com a funo FileExists(), conforme mostrado na linha if FileExists(Lista.Strings[Cont]) then... Do contrrio, pode-se tentar executar um MP3 que nem sequer est mais no HD e a teremos um erro na tela. A funo FileExists() retorna True se o arquivo existir e False se no existir. Caso o arquivo em questo no mais exista, o if pula para o ltimo else do bloco e adiciona mais 1 ao Cont, para tentar a faixa subseqente - at que uma faixa presente no disco seja encontrada. Note tambm outro teste com if que foi realizado: nas linhas if Cont > Lista.Count-1 then Cont := 0 estamos orientando nosso programa a buscar novamente a primeira msica da playlist (Cont := 0) caso o valor de Cont ultrapasse a quantidade de msicas existentes na listagem (isto , quando Cont > Lista.Count- 1, o que significa que no h prxima msica, mas que deve-se retornar ao comeo).

Ao mesmo tempo, aps iniciar a msica, pedimos que a ListBox mostrasse qual a faixa atualmente em execuo, selecionando-a com ListBox1.Selected[Cont] := True.

Observe tambm uma maneira diferente de nos referirmos ao MediaPlayer: logo no incio do cdigo, temos with MediaPlayer1 do begin. Isso no de todo necessrio, mas serve para tornar mais rpida a digitao. Sem a palavra reservada with, toda vez que nos referssemos a um mtodo ou propriedade do MediaPlayer, teramos que digitar o nome do componente:

     MediaPlayer1.FileName := Lista.Strings[Cont];
     MediaPlayer1.Open ;
     MediaPlayer1.Play;

Englobando esta mesma poro de cdigo em um with, basta chamar seus mtodos e propriedades que o Delphi j sabe a qual componente estamos nos referindo:

  with MediaPlayer1 do begin
   ...
     FileName := Lista.Strings[Cont];
     Open ;
     Play;
   ...
  end; //with MediaPlayer

Observe quer todo With deve terminar com um end (note o end que delimita seu final na linha terminada com end;//with MediaPlayer).


Ajustando o menu Popup

Devemos, neste momento, fazer uma pequena modificao num cdigo j implementado: o do menu Popup Remover faixa. Volte ao seu evento OnClick e adicione ao cdigo existente a linha em destaque abaixo:

if application.messagebox(pchar('Remover faixa '+ ListBox1.Items.strings[ListBox1.ItemIndex] + '?'), pchar(Caption),36) = IDYES then begin
 BtnStopClick(self);
 Lista.Delete(ListBox1.ItemIndex);
 ListBox1.DeleteSelected;
 
if Cont > 0 then
  Cont := Cont - 1;
end;

A linha que adicionamos faz uma chamada estratgica ao boto Stop. Como ainda no havamos codificado esse boto ao escrever o cdigo deste menu Popup, deixamos temporariamente esta linha de lado. Mas agora ela deve ser usada - e por um motivo muito simples: se a faixa que for excluda coincidir de ser justamente aquela que estiver em execuo naquele momento, o player ir se perder ao tentar continuar executando-a. Por isso, o melhor a fazer par-lo (chamando o prprio evento OnClick do boto BtnStop) para que o contador possa fazer os ajustes necessrios e a listagem possa ser ajustada nova quantidade de msicas (afinal, excluir uma faixa altera a quantidade de msicas presentes na lista).
 

Controlando o Volume do Som

Vamos ver como podemos aumentar ou diminuir o som dos alto-falantes. Para isso, adicione a Unit MMSystem clusula uses do seu aplicativo (observe o detalhe em vermelho na figura ao lado).

Depois, entre as sesses type e private, digite o seguinte:

    procedure TestaVolume;

 

Pressione CTRL+SHIFT+C para criar o corpo dessa nova procedure e, nela, implemente o seguinte cdigo:

procedure TForm1.TestaVolume;
 var
  WaveCaps : TWaveOutCaps;
  Volume : DWord;
begin
 
  if waveOutGetDevCaps(WAVE_MAPPER, @WaveCaps, sizeof(TWaveOutCaps)) = MMSYSERR_NOERROR then
  if (WaveCaps.dwSupport and WAVECAPS_VOLUME) <> 0 then begin
 
  WaveOutGetVolume(Integer(WAVE_MAPPER), @Volume);

  with TrackBar1 do
   Position := 100 - Trunc(LoWord(Volume) / $FFFF * 100);
  end;
end;

Aqui, temos uma varivel do tipo TWaveOutCaps e outra do tipo DWord. TWaveOutCaps um objeto que armazena dados do hardware de udio presente no sistema.

Para descobrir se teremos condio de modificar em tempo real o volume dos auto-falantes, usamos a funo WaveOutGetDeviceCaps( ) que armazenar as capacidades de udio do sistema na varivel WaveCaps. Se a funo retornar MMSYSERR_NOERROR significa que o hardware de udio est presente e no apresentou nenhum erro. A, testamos a propriedade dwSupport  de TWaveOutCaps com WAVECAPS_VOLUME. Quando testadas juntas, dessa maneira:

 if (WaveCaps.dwSupport and WAVECAPS_VOLUME)...

o resultado obtido ser diferente de zero (<> 0) se houver suporte para alterao de volume, e igual a zero caso contrrio. Portanto, se for diferente de zero, devemos obter qual a "posio" deste volume com a funo WaveOutGetVolume. Esta funo obtm um "id" (identificador) para o dispositivo de udio atravs do parmetro WAVE_MAPPER (que deve ser convertido para inteiro com Integer( ) para poder ser usado) e um "ponteiro" para a varivel Volume (@Volume). O Windows trabalha muito com "ponteiros", referenciados no Delphi por "arroba" (@).

Uma vez que os dados do volume esto armazenados na varivel Volume, precisamos "quebrar" esses dados em partes para poder atribuir o valor correto propriedade Position da TrackBar. A varivel Volume, do tipo DWord, um cardinal (um tipo de Inteiro) que armazena valores entre 0 e 65.535. O Windows costuma unir em um s nmero vrias informaes. Por exemplo, a varivel Volume contm, na verdade, informaes sobre os dois canais de udio - o da esquerda e o da direita. Mas precisamos de apenas um para determinar o volume atual - por essa razo, quebra-se a informao com LoWord(), para obtermos apenas uma parte dela. Depois, divide-se o valor obtido por $FFFF (que 65.535 em hexadecimal). A funo Trunc() serve apenas para "truncar" o resultado da diviso, garantindo que tenhamos um nmero inteiro como resposta. Ao final, a linha Position := 100 - Trunc(LoWord(Volume) / $FFFF * 100) atribui, em percentuais, a posio correta do volume do sistema naquele instante.

Agora, precisamos criar a funo que nos permitir modificar o volume. Para isso, entre as sesses type e private, digite o seguinte:

    procedure MudaVolume;


Pressione CTRL+SHIFT+C e complete o corpo da procedure conforme segue:

procedure TForm1.MudaVolume;
 var
  WaveCaps : TWaveOutCaps;
  VolDir, VolEsq : Word;
begin
 
  VolEsq := Trunc((TrackBar1.Position-100) / 100 * $FFFF);
  VolDir := Trunc((TrackBar1.Position-100) / 100 * $FFFF);
 
  if waveOutGetDevCaps(WAVE_MAPPER, @WaveCaps, sizeof(TWaveOutCaps)) = MMSYSERR_NOERROR then
   if (WaveCaps.dwSupport and WAVECAPS_VOLUME) <> 0 then
     WaveOutSetVolume(Integer(WAVE_MAPPER), MakeLong(VolEsq,VolDir));

end;


Aqui, as duas primeiras linhas so simples: apenas capturam a posio da TrackBar e atribuem, em percentuais, ao volume dos alto-falantes esquerdo e direito. Depois, testa-se novamente se possvel alterar o volume usando WaveOutGetDevCaps() e, em caso positivo, ajusta o novo volume com a funo WaveOutSetVolume(). Esta funo tambm usa o parmetro WAVE_MAPPER, que obtm um id para o dispositivo de udio e, depois, "une" os dois canais obtidos em um nico nmero inteiro longo (Longint), atravs da funo MakeLong().
 

ltimas Modificaes

Uma vez criadas as funes de volume, devemos cham-las nos locais corretos de nossa aplicao. A funo que testa o suporte modificao de volume deve ser chamada logo no evento OnCreate do formulrio:

TestaVolume;


A funo que altera o volume deve estar no evento OnChange da TrackBar:

MudaVolume ;

Para incrementar o software, podemos ainda colocar um componente Image (paleta Additional) no Panel2 para que possamos exibir uma figura no local. O arquivo zipado traz trs figuras JPG de sugesto, mas voc pode modificar a seu critrio. Ajuste o tamanho do componente Image para que fique quase igual s dimenses do Panel2. Depois, ajuste as propriedades Anchors do Image, deixando todos os itens em True. Por fim, altere a propriedade Stretch para True tambm. A propriedade Stretch, quando configurada dessa maneira,  faz com que a figura escolhida ajuste-se automaticamente ao tamanho do componente.

Para que o componente Image funcione a contento, ainda devemos acrescentar a Unit JPEG na clusulas Uses. Somente assim o componente estar apto a receber tambm figuras no formato JPG ou JPEG.
 

 

Melhorando o Programa

Podemos ainda acrescentar algumas outras funcionalidades ao programa. Por exemplo, que tal uma barra de progresso que mostre o andamento da faixa atual? Podemos usar o Timer que j temos no nosso form e adicionar uma ProgressBar, da paleta Win32. Posicione-a abaixo do controle de volume. Altere sua propriedade Smooth para True e ajuste sua propriedade Anchors para que akLeft, akRight e akBottom fiquem configuradas como True. No evento OnTimer do Timer1, faa as modificaes marcadas em destaque:

 if MediaPlayer1.Position = MediaPlayer1.Length then begin
  with MediaPlayer1 do begin
 Cont := Cont + 1;
 if Cont > Lista.Count-1 then
  Cont := 0;
 Close ;
 if FileExists(Lista.Strings[Cont]) then begin
  TimeFormat := tfHMS;
  FileName := Lista.Strings[Cont];
  Open ;
  Play;
 end
  else
    Cont := Cont + 1;
   end;
//with MediaPlayer
  end;
//if MediaPlayer

 if PLAYING then begin
  ProgressBar1.Max := MediaPlayer1.Length;
  ProgressBar1.Position := MediaPlayer1.Position;
end;


A linha TimeFormat := tfHMS apenas configura  o formato de tempo adotado pelo MediaPlayer. Aqui, estamos instruindo-o para que adote o padro, que Hora-Minuto-Segundo. Ao final do cdigo, se houver msica em execuo (isto , quando PLAYING = true) , ento a barra de progresso (ProgressBar1) dever ter sua posio mxima ajustada ao tamanho (Length) da faixa e sua posio atual igual posio da msica. Assim, sempre que a faixa do MediaPlayer estiver em "andamento", a posio (Position) da ProgressBar dever acompanh-lo.

 

Fonte: ASMC


Usando Virtual-Key Codes - 27-03-2015

Usando a classe TDictionary - 26-03-2015

Sua Primeira Aplicao FireMonkey - 22-03-2015

Efeitos de imagem no Delphi - 22-03-2015

Timer: criando um cronmetro - 10-09-2013

Criando um Navegador Web com TWebBrowser - 03-09-2013

Personalizando o DBNavigator - 01-09-2013

Como Esmaecer um Formulrio - 24-09-2010

Procure um assunto especfico:  

 

  - Todos os artigos -