Урок 1.4. Создаем mp3 player (проигрыватель) на основе библиотеки bass.dll.
На этом уроке мы научим наш проигрыватель сохранять настройки в ini файле.
При тестировании проигрывателя вы наверное заметили, что при каждом запуске приходиться заново устанавливать настройки эквалайзера, громкости, загружать плейлист. Это доставляет сильные неудобства. Сегодня мы научим наш плеер сохранять настройки и загружать их обратно из ini файла конфигурации.
Для того, чтобы программа могла работать с такими файлами, необходимо в разделе interface в uses в дополнение имеющегося списка дать ссылку на соответствующую библиотеку:
в разделе Var объявим переменную: IniFile: TIniFile;
var
Form_player: TForm_player;
i:integer; //номер проигрываемой песни в playlist
filename: string;//имя файла
Channel : DWORD;//
Mode: TPlayerMode;//PlayMode
//переменные для настройки эквалайзера
p: BASS_DX8_PARAMEQ;
fx: array[1..10] of integer;
//переменные визуализации
FFTPeacks : array [0..128] of Integer;
FFTFallOff : array [0..128] of Integer;
//переменная файла конфигурации
IniFile: TIniFile;
В инспекторе объектов для формы свойство AutoSize установим True.
А в событии OnCreate формы добавим строки:
var n,count:integer;
в теле процедуры:
//создание inifile с именем Config.ini
IniFile:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'Config.ini');
//загрузка настроек из inifile
//положение формы и размер
form_player.Left:=IniFile.ReadInteger('Form info','Left',285);
form_player.Top:=IniFile.ReadInteger('Form info','Top',168);
form_player.Width:=IniFile.ReadInteger('Form info','Width',520);
form_player.Height:=IniFile.ReadInteger('Form info','Height',501);
//громкость звука
trackbar1.position:=IniFile.ReadInteger('Volue','trackbar1.position',5);
//настройки эквалайзера
trackbar3.position:=IniFile.ReadInteger('EQLayzer','trackbar3.position',15);
trackbar4.position:=IniFile.ReadInteger('EQLayzer','trackbar4.position',15);
trackbar5.position:=IniFile.ReadInteger('EQLayzer','trackbar5.position',15);
trackbar6.position:=IniFile.ReadInteger('EQLayzer','trackbar6.position',15);
trackbar7.position:=IniFile.ReadInteger('EQLayzer','trackbar7.position',15);
trackbar8.position:=IniFile.ReadInteger('EQLayzer','trackbar8.position',15);
trackbar9.position:=IniFile.ReadInteger('EQLayzer','trackbar9.position',15);
trackbar10.position:=IniFile.ReadInteger('EQLayzer','trackbar10.position',15);
trackbar11.position:=IniFile.ReadInteger('EQLayzer','trackbar11.position',15);
trackbar12.position:=IniFile.ReadInteger('EQLayzer','trackbar12.position',15);
//количество записей в плейлисте
Count:=IniFile.ReadInteger('ItemsCount','Count',0);
//загрузка плейлиста
if Count<>0 then
begin
for n := 0 to Count - 1 do
ListBox1.Items.Add(IniFile.ReadString('PlayList', 'file' + IntToStr(n+1),'Ошибка чтения'));
//установка на первую запись плейлиста
Filename:=ListBox1.Items.Strings[0];
ListBox1.ItemIndex:=0;
end;
procedure TForm_player.FormCreate(Sender: TObject);
var n, count:integer;
begin
//установка громкости
trackbar1.Min:=0;
trackbar1.Max:=10;
trackbar1.Position:=5;
//установка баланса
trackbar2.Min:=-5;
trackbar2.Max:=5;
trackbar2.Position:=0;
// проверка корректности загруженной BASS.DLL
if (HIWORD(BASS_GetVersion) <> BASSVERSION) then
begin
MessageBox(0,'Не корректная версия BASS.DLL',nil,MB_ICONERROR);
Halt;
end;
// Инициализация аудио - по умолчанию, 44100hz, stereo, 16 bits
if not BASS_Init(-1, 44100, 0, Handle, nil) then
begin
MessageBox(0,'Ошибка инициализация аудио',nil,MB_ICONERROR);
Halt;
end;
//создание inifile с именем Config.ini
IniFile:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'Config.ini');
//загрузка настроек из inifile
//положение формы и размер
form_player.Left:=IniFile.ReadInteger('Form info','Left',285);
form_player.Top:=IniFile.ReadInteger('Form info','Top',168);
form_player.Width:=IniFile.ReadInteger('Form info','Width',520);
form_player.Height:=IniFile.ReadInteger('Form info','Height',501);
//громкость звука
trackbar1.position:=IniFile.ReadInteger('Volue','trackbar1.position',5);
//настройки эквалайзера
trackbar3.position:=IniFile.ReadInteger('EQLayzer','trackbar3.position',15);
trackbar4.position:=IniFile.ReadInteger('EQLayzer','trackbar4.position',15);
trackbar5.position:=IniFile.ReadInteger('EQLayzer','trackbar5.position',15);
trackbar6.position:=IniFile.ReadInteger('EQLayzer','trackbar6.position',15);
trackbar7.position:=IniFile.ReadInteger('EQLayzer','trackbar7.position',15);
trackbar8.position:=IniFile.ReadInteger('EQLayzer','trackbar8.position',15);
trackbar9.position:=IniFile.ReadInteger('EQLayzer','trackbar9.position',15);
trackbar10.position:=IniFile.ReadInteger('EQLayzer','trackbar10.position',15);
trackbar11.position:=IniFile.ReadInteger('EQLayzer','trackbar11.position',15);
trackbar12.position:=IniFile.ReadInteger('EQLayzer','trackbar12.position',15);
//количество записей в плейлисте
Count:=IniFile.ReadInteger('ItemsCount','Count',0);
//загрузка плейлиста
if Count<>0 then
begin
for n := 0 to Count - 1 do
ListBox1.Items.Add(IniFile.ReadString('PlayList', 'file' + IntToStr(n+1),'Ошибка чтения'));
//установка на первую запись плейлиста
Filename:=ListBox1.Items.Strings[0];
ListBox1.ItemIndex:=0;
end;
end;
Для события OnClose формы добавим следующий код:
var n:integer;
в теле процедуры
//сохраняем настройки в inifile
//форма
IniFile.WriteInteger('Form info','Left',Left);
IniFile.WriteInteger('Form info','Top',Top);
IniFile.WriteInteger('Form info','Width',Width);
IniFile.WriteInteger('Form info','Height',Height);
//громкость звука
IniFile.WriteInteger('Volue','trackbar1.position',trackbar1.position);
//эквалайзер
IniFile.WriteInteger('EQLayzer','trackbar3.position',trackbar3.position);
IniFile.WriteInteger('EQLayzer','trackbar4.position',trackbar4.position);
IniFile.WriteInteger('EQLayzer','trackbar5.position',trackbar5.position);
IniFile.WriteInteger('EQLayzer','trackbar6.position',trackbar6.position);
IniFile.WriteInteger('EQLayzer','trackbar7.position',trackbar7.position);
IniFile.WriteInteger('EQLayzer','trackbar8.position',trackbar8.position);
IniFile.WriteInteger('EQLayzer','trackbar9.position',trackbar9.position);
IniFile.WriteInteger('EQLayzer','trackbar10.position',trackbar10.position);
IniFile.WriteInteger('EQLayzer','trackbar11.position',trackbar11.position);
IniFile.WriteInteger('EQLayzer','trackbar12.position',trackbar12.position);
//количество файлов в PlayList
IniFile.WriteInteger('ItemsCount','Count',ListBox1.Items.Count);
//очистка секции PlayList
IniFile.EraseSection('PlayList');
//выгрузка из PlayList
for n := 0 to ListBox1.Items.Count - 1 do
IniFile.WriteString('PlayList', 'file' + IntToStr(n+1), ListBox1.Items.Strings[n]);
//Время создания PlayList
IniFile.WriteTime('Time','Write time',Time);
//Освобождаем объекты перед закрытием
IniFile.Free;
procedure TForm_player.FormClose(Sender: TObject; var Action: TCloseAction);
var n:integer;
begin
//сохраняем настройки в inifile
//форма
IniFile.WriteInteger('Form info','Left',Left);
IniFile.WriteInteger('Form info','Top',Top);
IniFile.WriteInteger('Form info','Width',Width);
IniFile.WriteInteger('Form info','Height',Height);
//громкость звука
IniFile.WriteInteger('Volue','trackbar1.position',trackbar1.position);
//эквалайзер
IniFile.WriteInteger('EQLayzer','trackbar3.position',trackbar3.position);
IniFile.WriteInteger('EQLayzer','trackbar4.position',trackbar4.position);
IniFile.WriteInteger('EQLayzer','trackbar5.position',trackbar5.position);
IniFile.WriteInteger('EQLayzer','trackbar6.position',trackbar6.position);
IniFile.WriteInteger('EQLayzer','trackbar7.position',trackbar7.position);
IniFile.WriteInteger('EQLayzer','trackbar8.position',trackbar8.position);
IniFile.WriteInteger('EQLayzer','trackbar9.position',trackbar9.position);
IniFile.WriteInteger('EQLayzer','trackbar10.position',trackbar10.position);
IniFile.WriteInteger('EQLayzer','trackbar11.position',trackbar11.position);
IniFile.WriteInteger('EQLayzer','trackbar12.position',trackbar12.position);
//количество файлов в PlayList
IniFile.WriteInteger('ItemsCount','Count',ListBox1.Items.Count);
//очистка секции PlayList
IniFile.EraseSection('PlayList');
//выгрузка из PlayList
for n := 0 to ListBox1.Items.Count - 1 do
IniFile.WriteString('PlayList', 'file' + IntToStr(n+1), ListBox1.Items.Strings[n]);
//Время создания PlayList
IniFile.WriteTime('Time','Write time',Time);
//Освобождаем объекты перед закрытием
IniFile.Free;
Bass_Stop();
BASS_StreamFree(channel);
Bass_Free;
end;
procedure TForm_player.Button6Click(Sender: TObject); begin i:=ListBox1.ItemIndex; Filename:=ListBox1.Items.Strings; if DeleteFile('filename') then begin ListBox1.Items.Delete(i); ................end else ....................; end;
ну так в том то и дело, я сделал все как в 30 комментарии, но бегунок можно только перетаскивать, а при нажатии на какую либо область image1 ничего не происходит...
Сразу не понял вопроса.))) Добавьте событие OnMouseDown для Image1:
Code
procedure TForm_player.Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin //Проверяем если клик произошел в конце скроллбара //то чтобы движок не вылазил за скроллбар //устанавливаем ему позицию ширина бара минус ширина движка //и минус 1 иначе не работает //в противном случае двигаем движок в соответствии с //положением мыши. if X+image1.Left>image1.Left+image1.Width-image2.Width then Image2.left:=image1.Left+image1.Width-image2.Width-1 else Image2.left:=X+image1.Left; //устанавливаем позицию проигрывания в соответствии //с положением движка bass_ChannelSetPosition(Channel, round((image2.Left-image1.left)/((image1.Width-image2.Width)/BASS_ChannelGetLength(channel, 0))), 0); end;
а для громкости, вместо этого: bass_ChannelSetPosition(Channel, round((image2.Left-image1.left)/((image1.Width-image2.Width)/BASS_ChannelGetLength(channel, 0))), 0); что надо писать ?
Здравствуйте,как можно сделать перемотку песен? вместо скроллбара стоит прогрессбар. в процедуре MouseActivate стоит код: BASS_ChannelSetPosition(Channel, sprogressbar1.Position, 0); но при нажатии позицию он не меняет.
Привет Xaramamburu заранее спасибо за уроки они очень помогли. Скажите как исправить эту ошибку??
[Error]mp3.pas(58):';'expected but 'IMPLEMENTATION' found [Fatal Error]Unit2.pas(30): Could not compile used unit 'mp3'
Дело в том что я переместил еквалайзер в unit1 а плейлист в unit2 подключил unit1, unit2, bass как описано на уроке но выдает ошибку ругается на эти строчки в mp3:
Как вынести эквалайзер, смотрите на форуме здесь: http://basicsprog.ucoz.ru/forum/4-8-1 там есть рабочий пример. Как вынести плейлист есть в комментариях к уроку 1.3. По вашим ошибкам сложно, что то сказать. Первая говорит, что ожидалась ';', вторая, что не может использовать при компиляции модуль 'mp3'. Причин этих ошибок может быть множество, нужно видеть весь код целиком. Если не разберетесь присылайте код мне на почту, попробую помочь.
Ура, у меня получилось добавить к основной библиотеке ещё несколько форматов воспроизведения. После строки MessageBox(0,'Не корректная версия BASS.DLL',nil,MB_ICONERROR); Halt; end; нужно добавить: BASS_PluginLoad ('Имя_плагина.dll', 0); не забыть продекларировать плагин в uses и в процедуре procedure TForm_player.FormClose добавить строку bass_pluginfree(0);
и ещё вопросик:), при открытии через кнопку(открыть) файлы добавляются и нажав на кнопку play запускается проигрывание песни, но если загрузить песню посредством drag and drop и нажать play пишет что файл не существует-->если первую песню закидывать посредством drag and drop запустить её можно только двойным кликом в плей листе.Надеюсь вы поняли о чём я, так вот Как бы это исправить? пробовал сам но что то не выходит..
В начале процедуры drag and drop нужно проверить не пустой ли плейлист и запомнить номер текущей песни. //проверяем если PlayList не пустой то запоминаем номер текущей песни //иначе устанавливаем номер песни 0 (первая позиция в PlayList) if listbox1.Count<>0 then i:=ListBox1.ItemIndex else i:=0;
В конце процедуры нужно вспомнить эти значения обратно: //запоминаем имя файла текущей песни в плейлисте Filename:=ListBox1.Items.Strings[i]; //Выделяем эту песню в PlayList ListBox1.ItemIndex:=i; Да если вы уже использовали переменную Filename в процедуре drag and drop, то ее придется заменить например на Filename1.))))
Да если вы уже использовали переменную Filename в процедуре drag and drop, то ее придется заменить например на Filename1.))))
Вот сама процедура
//процедура извлечения имен файлов при перетаскивании procedure TForm_player.WMDropFiles(var Msg: TWMDropFiles); var i: integer;//счетчик файлов CountFile: integer;//Количество файлов size: integer;//длина строки, содержащей путь к файлу Filename: PChar; //указатель на имя файла begin try //Функция DragQueryFile извлекает имена перемещенных мышью файлов //получаем количество перемещаемых файлов CountFile := DragQueryFile(Msg.Drop, $FFFFFFFF, Filename, 255); //извлекаем пути до перемещаемых файлов и добавляем их в ListBox for i := 0 to (CountFile - 1) do begin //получаем длину строки, содержащей путь к файлу size := DragQueryFile(Msg.Drop, i , nil, 0)+1; //выделяем память под строку с именем файла Filename:= StrAlloc(size); //получаем непосредственно само имя файла и путь DragQueryFile(Msg.Drop,i , Filename, size); //добавляем его в ListBox если расширение файла = '.mp3' //функция lowercase понижает регистр символов if lowercase(ExtractFileExt(StrPas(filename)))='.mp3' then listbox1.items.add(StrPas(Filename)); //освобождаем строку StrDispose(Filename); end; finally DragFinish(Msg.Drop); // отпуститим файл end; end;
Можно прям впихнуть туда то что надо), а то боюсь до меня так и не дойдёт как сделать:О
Вот в этом коде который вы привели замените везде Filename на Filename1, т.к. переменная Filename уже объявлена как глобальная в основной программе. Далее после begin добавьте: //проверяем если PlayList не пустой то запоминаем номер текущей песни //иначе устанавливаем номер песни 0 (первая позиция в PlayList) if listbox1.Count<>0 then i:=ListBox1.ItemIndex else i:=0; а в конце процедуры в разделе finally добавьте: //запоминаем имя файла текущей песни в плейлисте Filename:=ListBox1.Items.Strings[i]; //Выделяем эту песню в PlayList ListBox1.ItemIndex:=i; должно работать:) Просьба, не дублируйте вопросы на форуме и в комментариях.
кстатии на счет этой ошибки, у меня есть кнопка которая включает предыдущий трек, все работает норм, но когда я пытаюсь сделать кнопку "вперед" путем изменения в этом коде if ListBox1.ItemIndex > 0 then begin i:=i+1; Filename:=ListBox1.Items.Strings[i]; ListBox1.ItemIndex:=i; MoDe:=stop; PLaYeR; end else exit;
выдает эту ошибку, напишите подробнее где нужно заменить i на i1 )
С помощью отрисовки, как то так: Для Listboxa свойство Style установите lbOwnerDrawFixed или lbOwnerDrawVariable, а для события OnDrawItem пишем код:
procedure TForm_player.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); const W = 16; H = 16; begin with (Control as TListBox).Canvas do begin FillRect(Rect); end; with (control as TListBox).canvas do begin Font.Color := clGray; Font.Size := 9; Brush.Style := bsClear; Brush.Color := clGray; SetBkMode(ListBox1.canvas.Handle, TRANSPARENT); TextOut(Rect.Left + w, Rect.Top, IntToStr(Index) + '. ' + extractfilename(Listbox1.Items[index])); end; end;
Посмотрите на форуме, там только что обсуждалась эта тема, правда там этот же код написан немножко по другому, но наберите кусок этого кода в поисковике и найдете его описание. )))))))))))))
Здравствуйте,помогите пожалуйста, я переместил плейлист на 2 форму,но теперь перестал он сохраняться выдает ошибку: access violation at address 0045e4df in module 'cl.exe'. read of adress 000002f8.
if Count<>0 then begin for n := 0 to Count - 1 do Form1.ListBox1.Items.Add(IniFile.ReadString('PlayList', 'file' + IntToStr(n+1),'Ошибка чтения')); - ругается на эту строчку Filename:=form1.ListBox1.Items.Strings[0]; form1.ListBox1.ItemIndex:=0; end; end;
У вас сейчас ListBox находится на другой форме и к нему надо обращаться соответственно Имя новой формы.ListBox1 и т.д. Плюс модуль новой формы должен быть прописан в основной форме в модуле Uses.
Проблему можно решить следующим образом: перенесите часть кода из события OnCreate в событие OnShow формы или в событие OnCreate формы с плейлистом : procedure TForm1.FormShow(Sender: TObject); var n, count:integer; begin //количество записей в плейлисте Count:=IniFile.ReadInteger('ItemsCount','Count',0); //загрузка плейлиста if Count<>0 then begin for n := 0 to Count-1 do Form2.ListBox1.Items.Add(IniFile.ReadString('PlayList', 'file' + IntToStr(n+1), 'Ошибка чтения')); //установка на первую запись плейлиста Filename:=Form2.ListBox1.Items.Strings[0]; Form2.ListBox1.ItemIndex:=0; end; end;
Дело в том, что в момент выполнения события OnCreate первой формы вторая, на которой находится плейлист, еще не создана. ))))))))))))