Конференция "Media" » Bass player [D7]
 
  • Ламер © (04.03.08 17:15) [0]
    Я только начинаю программировать.Решил написать плеер с использованием библиотеки басс.Но возникла проблема.Как сделать так,чтобы песни играли одна за другой и после воспроизведения песни она не начанала играть снова одна и таже???

    ВОТ ИСХОДНЫЙ КОД ПЛЕЕРА

    unit Unit1;

    interface

    uses
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
     Dialogs,Bass,MMSYSTEM, FileCtrl, StdCtrls, ExtCtrls, ComCtrls;
    type
     TChannelType = (ctUnknown, ctStream, ctMusic);

    type
     TForm1 = class(TForm)
       ComboBox1: TComboBox;
       Label1: TLabel;
       Label2: TLabel;
       lbPosLen: TLabel;
       Button1: TButton;
       barSeek: TTrackBar;
       tmrMain: TTimer;
       Button2: TButton;
       Button3: TButton;
       procedure PlayList(P: string);
       procedure FormCreate(Sender: TObject);
       procedure FormDestroy(Sender: TObject);
         procedure BASS_SetPosition(const Value: DWORD);
       procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
         Y: Integer);
       procedure Button1Click(Sender: TObject);
       procedure tmrMainTimer(Sender: TObject);
       procedure barSeekChange(Sender: TObject);
       procedure Button2Click(Sender: TObject);
       procedure Button3Click(Sender: TObject);
       procedure ComboBox1Click(Sender: TObject);
     private
      function BASS_GetLength: DWORD;
       function BASS_GetPosition: DWORD;
       procedure play;

     public
       { Public declarations }
     end;
    var
     Form1: TForm1;
      MX: integer;
    MY: integer;
      floatable: DWORD; // floating-point channel support?
     chan: DWORD;
     CHANGE_POS: Boolean = True;
     FFileLength: string;

    implementation

    {$R *.dfm}

    function TForm1.BASS_GetLength: DWORD;
    var
     SongLength: Int64;
     FloatLen: FLOAT;
    begin
      SongLength:= BASS_ChannelGetLength(chan);
      if SongLength < 0 then SongLength:= 0;
      FloatLen:= BASS_ChannelBytes2Seconds(chan, SongLength);
      Result:= Round(1000 * FloatLen);
    end;

    function TForm1.BASS_GetPosition: DWORD;
    var
     SongPos: Int64;
     FloatPos: FLOAT;
    begin
         SongPos:= BASS_ChannelGetPosition(chan);
         if SongPos < 0 then SongPos:= 0;
         FloatPos:= BASS_ChannelBytes2Seconds(chan, SongPos);
         Result:= Round(1000 * FloatPos);
    end;

    procedure TForm1.BASS_SetPosition(const Value: DWORD);
    var
     SongPos: Int64;
    begin
     SongPos:= BASS_ChannelSeconds2Bytes(chan, Value / 1000);
    BASS_ChannelSetPosition(chan, SongPos);
     end;
     
    var
    SoundP: string[255];

    procedure TForm1.PlayList(P: string);
    var
     SearchRec: TSearchRec; // структура SearchRec содержит информацию                         // о файле, удовлетворяющем условию поиска
    begin
     ComboBox1.Clear;
     // сформировать список аудиофайлов
     if FindFirst(P + '*.mp3', faAnyFile, SearchRec) =0 then
        begin
    ComboBox1.Items.Add(SearchRec.Name); // добавим имя этого файла в список
             while (FindNext(SearchRec) = 0) do
          ComboBox1.Items.Add(SearchRec.Name);
         end;
    end;
    procedure TForm1.FormCreate(Sender: TObject);
    begin
    PlayList('');
      ComboBox1.ItemIndex := 0;
    // check the correct BASS was loaded
    if (HIWORD(BASS_GetVersion) <> BASSVERSION) then
    begin
     MessageBox(0,'An incorrect version of BASS.DLL was loaded',0,MB_ICONERROR);
     Halt;
    end;
     BASS_SetConfig(BASS_CONFIG_FLOATDSP, 1);
     if not BASS_Init(-1, 44900, 0, Handle, nil) then
     begin
       MessageBox(0, 'Can''t initialize device', 0, 0);
       Halt;
     end;
     floatable := BASS_StreamCreate(44900, 2, BASS_SAMPLE_FLOAT, nil, 0);
     if (floatable > 0) then
     begin
       BASS_StreamFree(floatable); // woohoo!
       floatable := BASS_SAMPLE_FLOAT;
     end
    end;

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
    BASS_Free;
    end;
    procedure TForm1.play;
    var
     info: BASS_CHANNELINFO;
     i:sTRING;
    begin
    ComboBox1.ItemIndex := ComboBox1.ItemIndex + 1;
     i:=SoundP + ComboBox1.Items[ComboBox1.itemIndex];
     // free both MOD and stream, it must be one of them! :)
     BASS_MusicFree(chan);
     BASS_StreamFree(chan);

     chan := BASS_StreamCreateFile(False, PChar(i), 0, 0, floatable or BASS_SAMPLE_LOOP);
     if (chan = 0) then
       chan := BASS_MusicLoad(False, PChar(i), 0, 0, BASS_MUSIC_LOOP or BASS_MUSIC_RAMPS or floatable, 0);

     BASS_ChannelGetInfo(chan, info);
     if (info.chans <> 2) then // only stereo is allowed
     begin
       BASS_MusicFree(chan);
       BASS_StreamFree(chan);
       MessageBox(0, 'Неподдерживаемый формат', 0, 0);
       Exit;
     end;
     tmrMain.Enabled:= True;
     BASS_ChannelPlay(chan, False);
    end;

    procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
     Y: Integer);
    begin
    if Shift<>[ssLeft] then
    begin
    MX:=X;
    MY:=Y;
    end else
    begin
    Left:=Left+X-MX;
    Top:=Top+Y-MY;
    end;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var
     Root: string;      // корневой каталог
     pwRoot : PWideChar;
     Dir: string;
    begin
     Root := ''; // корневой каталог - папка Рабочий стол
     GetMem(pwRoot, (Length(Root)+1) * 2);
     pwRoot := StringToWideChar(Root,pwRoot,MAX_PATH*2);
     if not SelectDirectory('Выберите папку', pwRoot, Dir)
        then Dir :=''
        else Dir := Dir+'\';

     // каталог, в котором находятся аудиофайлы выбран
     SoundP := Dir;
     PlayList(SoundP);
    end;

    procedure TForm1.tmrMainTimer(Sender: TObject);
    var
    i:sTRING;
    begin
    if not barSeek.Enabled then
         barSeek.Enabled:= True;
       CHANGE_POS:= False;
       barSeek.Position:= (BASS_GetPosition * DWORD(barSeek.Max)) div BASS_GetLength;
       CHANGE_POS:= True;
       lbPosLen.Caption:=
         FormatDateTime('nn:ss', BASS_GetPosition / (1000 * 24 * 60 * 60));
    end;

    procedure TForm1.barSeekChange(Sender: TObject);
    var
     PD: Single;
    begin
     if CHANGE_POS then
     begin
       PD:= BASS_GetLength / barSeek.Max;
       BASS_SetPosition(Round(barSeek.Position * PD));
     end;
    end;

    procedure TForm1.Button2Click(Sender: TObject);
    begin
           ComboBox1.ItemIndex := ComboBox1.ItemIndex + 1;
           play;
    end;

    procedure TForm1.Button3Click(Sender: TObject);
    begin
           ComboBox1.ItemIndex := ComboBox1.ItemIndex - 1;
          play;
    end;

    procedure TForm1.ComboBox1Click(Sender: TObject);
    begin
    play;
    end;

    end.
  • Dimaxx © (04.03.08 17:34) [1]
    В PlayList ты забыл FindClose. Далее, 44900 откуда взялось? Вроде стандартное значение 44100.

    Я уже не помню все функции bass, но нужно отслеживать окончание проигрывания очередного файла и открывать следующий. Например, отслеживать позицию.
  • Ламер © (04.03.08 18:11) [2]
    ТО что надо отследить позицию окончания песни это я понял но как это сделать? Пробовал так : if (Bass_GetLength=Bass_GetPosition) then begin
    ComboBox1.ItemIndex := ComboBox1.ItemIndex + 1;
          play;
    end;

    Но ничего из этого не выходит.Дайте пожалуйста конкретный код!
  • programania © (04.03.08 20:03) [3]
    > и после воспроизведения песни она не начанала играть снова одна и таже???

    убрать BASS_SAMPLE_LOOP

    > Как сделать так,чтобы песни играли одна за другой

    в timer
    if (BASS_ChannelIsActive(chan)<>BASS_ACTIVE_PLAYING) and
      (BASS_ChannelIsActive(chan)<>BASS_ACTIVE_PAUSED ) then
    запустить следущую
  • Ламер © (04.03.08 21:03) [4]
    Спасибо.Песни играют одна за другой но меняются они через каждую секунду Т.К В ТАЙМЕРЕ ИНТЕРВАЛ 1 СЕК как сделать так ,чтобы интервал таймера был равен длине песни???.Мне надо,чтобы песня проиграла до конца.  HELP !!!!!!
  • Ламер © (04.03.08 21:09) [5]
    ВСЕ ПОЛУЧИЛОСЬ!!!Просто надо было поставить интервал таймера больше длины любой песни. С.П.А.С.И.Б.О. ОГРОМНОЕ ВСЕМ!!!
  • Ламер © (04.03.08 21:17) [6]
    Извиняюсь нихрена не получилось возвращаюсь к предыдущему вопросу
    помогите я уже запарился!
  • Efir (04.03.08 23:38) [7]
    Покажи исходник процедуры с таймером.
  • Efir (04.03.08 23:43) [8]
    Сделай так:

    В таймере
    if chan>0 then
      case BASS_ChannelIsActive(chan) of
         BASS_ACTIVE_PLAYING: показываешь статус проигрывания;
         BASS_ACTIVE_STOPPED: переходишь на след. мелодию.
      end;

    Соответственно при нажатии на кнопку стоп освобождаешь chan.
  • Ламер © (10.03.08 19:10) [9]
    Извините .Знаю ,что я тупой!!! Я разместил здесь исходник плеера.КТО-НИБУДЬ может исходя из него выложить код который будет решать мою проблему Я ТУПОЙ !!! показываешь статус проигрывания-Как его показывать???
  • Ламер © (10.03.08 19:38) [10]
    Ауууу!!!
  • Efir (10.03.08 23:13) [11]
    Где-то так:

    var
     TrackTime:Double;
     TrackPos:integer;
    begin
     if chan>0 then
       case BASS_ChannelIsActive(chan) of
         BASS_ACTIVE_PLAYING:
           begin
             TrackPos:integer:=BASS_ChannelGetPosition(chan); - текущая позиция таймера
             TrackTime:=BASS_ChannelBytes2Seconds(chan, TrackPos); - текущее время в секундах
           end;
  • Efir (10.03.08 23:14) [12]
    Точнее не текущая позиция таймера, а просто - текущая позиция.
Есть новые Нет новых   [133929   +472][b:0][p:0]