Как написать программу для mp3 плеера

Russian (Pусский) translation by Yuri Yuriev (you can also view the original English article)

Платформа Android предоставляет ресурсы для управления воспроизведением мультимедиа, которые ваши приложения могут использовать для создания интерфейса между пользователем и его музыкальными файлами. В этой серии уроков мы создадим базовый музыкальный плеер для Android. Приложение представит список песен на устройстве, чтобы пользователь мог выбирать их для воспроизведения. Приложение будет управлять воспроизведением и продолжит исполнение, когда пользователь выйдет из приложения, при этом будет отображаться уведомление.

Введение

Для создания music player потребуется класс ContentResolver для извлечения треков на устройстве, класс MediaPlayer для воспроизведения звука и класс MediaController для управления воспроизведением. Мы также будем использовать Service для воспроизведения звука, когда пользователь не взаимодействует напрямую с приложением. Дальше можете не смотреть, если вы промежуточный разработчик Android, и, если уже создали несколько приложений, вам будет неинтересно. Вот предварительный вид готового приложения:

Android Music PlayerAndroid Music PlayerAndroid Music Player

В этом уроке мы создадим приложение и запросим пользовательское устройство для аудиофайлов с использованием классов ContentResolver и Cursor. В следующей части мы будем использовать образец Adapter для показа песен в виде списка, начала воспроизведения при выборе элемента из списка. В последнем выпуске серии мы используем класс MediaController, чтобы дать пользователю контроль над воспроизведением, реализовать функции перемотки вперёд и назад и включить функцию shuffle. По окончании серии мы рассмотрим другие аспекты воспроизведения media, которые могут улучшить приложение, такие как обработка фокуса аудио, представление медиафайлов в разных видах и воспроизведение потокового media .

1. Создание и настройка нового проекта

Шаг 1

Создайте новый проект Android. Если вы используете Eclipse, то пусть IDE (Integrated Development Environment) создаст для вас основной класс Activity и файл макета. Для некоторых кодов, которые мы используем в этой серии, понадобится минимальный уровень API 16, так что вам нужно будет сделать дополнительные шаги для поддержки более старых версий. Когда проект будет создан, откройте файл Manifest проекта. Внутри элемента manifest добавьте следующее разрешение:

<uses-permission android:name="android.permission.WAKE_LOCK" />

Мы сделаем это разрешение, чтобы воспроизведение музыки продолжалось, когда устройство не работает. В вашем Manifest должен быть элемент для основного класса Activity. Добавьте следующие атрибуты в элемент activity, чтобы установить screenOrientation и launchMode:

<activity
  android:name="com.example.musicplayer.MainActivity"
  android:label="@string/app_name"
  android:launchMode="singleTop"
  android:screenOrientation="portrait" >

Для простоты мы будем придерживаться книжной ориентации. launchMode поможет процессу перехода к приложению после его удаления. Мы отобразим уведомление о текущей песне, нажатие на уведомление вернёт пользователя в приложение. Мы также будем использовать класс Service для воспроизведения музыки. Добавьте следующую строку в Manifest проекта внутри элемента application и после элемента activity:

<service android:name="com.example.musicplayer.MusicService" />

Измените имя пакета, как хотите и измените имя класса, если хотите.

Шаг 2

Откройте основной файл layout проекта и замените его на следующий layout:

<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical"
  android:background="#FF330000"
  tools:context=".MainActivity" >

  <ListView
    android:id="@+id/song_list"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >
  </ListView>

</LinearLayout>

Обязательно измените атрибут tools:context, если ваш основной класс Activity называется по-другому. Макет включает ListView, в котором мы представим список песен.

Мы собираемся включить два пункта меню для переключения функции перемешивания и выхода из приложения. Откройте файл главного меню (res/menu/main.xml) и замените его содержимое следующим:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

  <item
    android:id="@+id/action_shuffle"
    android:icon="@drawable/rand"
    android:orderInCategory="1"
    android:showAsAction="always"
    android:title="Shuffle"/>

  <item
    android:id="@+id/action_end"
    android:icon="@drawable/end"
    android:orderInCategory="2"
    android:showAsAction="always"
    android:title="End"/>

</menu>

Если нравится, вы можете хранить строки заголовка в файле res/values/strings.xml. Эти два элемента относятся к drawable файлам. Создайте собственные или используйте эти два изображения для начала:

Android Music Player Random Button
Android Music Player End Button

Мы будем использовать и значок уведомления о воспроизведении. Создайте его или используйте следующий:

Android Music Player Play Button

Код будет ссылаться на изображения, используя имена rand, end и play, поэтому убедитесь, что вы используете одни и те же имена файлов. Скопируйте изображения в папку (-и) drawables вашего проекта. Мы будем реализовывать эти действия позже.

2. Запрос устройства для песен

Шаг 1

Попробуем запросить устройство пользователя для аудиофайлов. Во-первых, добавьте новый класс Song. Мы будем использовать этот класс для моделирования данных одного звукового файла. В объявлении класса добавьте три переменные экземпляра данных, которые мы сохраним для каждого трека:

private long id;
private String title;
private String artist;

Затем добавьте метод конструктора, в котором мы создаём экземпляры переменных:

public Song(long songID, String songTitle, String songArtist) {
  id=songID;
  title=songTitle;
  artist=songArtist;
}

Наконец, добавьте методы get для переменных экземпляра:

public long getID(){return id;}
public String getTitle(){return title;}
public String getArtist(){return artist;}

Если вы планируете использовать больше информации о треке, вы можете добавить дополнительные переменные экземпляра в класс.

Шаг 2

Откройте основной класс Activity и добавьте imports:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import android.net.Uri;
import android.content.ContentResolver;
import android.database.Cursor;
import android.widget.ListView;

Объявите следующие переменные экземпляра перед методом onCreate:

private ArrayList<Song> songList;
private ListView songView;

Мы будем хранить песни в списке и отображать их в экземпляре ListView в главном layout. В onCreate после установки вида содержимого извлеките экземпляр ListView, используя ID, который мы дали ему в главном макете:

songView = (ListView)findViewById(R.id.song_list);

Создайте список, как показано ниже:

songList = new ArrayList<Song>();

Затем в объявлении основного класса Activity после существующих методов создайте вспомогательный метод для извлечения информации о звуковом файле:

public void getSongList() {
  //retrieve song info
}

Внутри этого метода создайте экземпляр ContentResolver, извлеките URI для внешних музыкальных файлов и создайте экземпляр Cursor, используя экземпляр ContentResolver для запроса музыкальных файлов:

ContentResolver musicResolver = getContentResolver();
Uri musicUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor musicCursor = musicResolver.query(musicUri, null, null, null, null);

Теперь мы можем перебрать результаты, сначала проверив, что у нас достоверные данные:

if(musicCursor!=null && musicCursor.moveToFirst()){
  //get columns
  int titleColumn = musicCursor.getColumnIndex
    (android.provider.MediaStore.Audio.Media.TITLE);
  int idColumn = musicCursor.getColumnIndex
    (android.provider.MediaStore.Audio.Media._ID);
  int artistColumn = musicCursor.getColumnIndex
    (android.provider.MediaStore.Audio.Media.ARTIST);
  //add songs to list
  do {
    long thisId = musicCursor.getLong(idColumn);
    String thisTitle = musicCursor.getString(titleColumn);
    String thisArtist = musicCursor.getString(artistColumn);
    songList.add(new Song(thisId, thisTitle, thisArtist));
  }
  while (musicCursor.moveToNext());
}

Сначала мы извлекаем индексы столбцов для интересующих нас элементов данных для каждой песни, затем мы используем их для создания нового объекта Song и добавления его в список, перед тем как продолжить обзор результатов.

Вернитесь в onCreate после кода, который мы добавили, вызовите этот новый метод:

getSongList();

3. Отображение композиций

Шаг 1

Теперь мы можем отобразить список песен в пользовательском интерфейсе. В методе onCreate после вызова вспомогательного метода, который мы создали минуту назад, давайте отсортируем данные так, чтобы песни представлялись в алфавитном порядке:

Collections.sort(songList, new Comparator<Song>(){
  public int compare(Song a, Song b){
    return a.getTitle().compareTo(b.getTitle());
  }
});

Мы используем переменную title в классе Song, используя добавленные методы get, чтобы реализовать метод compare, сортируя песни по заголовкам.

Шаг 2

Определим layout для представления каждой песни в списке. Добавьте новый файл в папку res/layout вашего проекта, назвав его song.xml и введя следующее:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:onClick="songPicked"
  android:orientation="vertical"
  android:padding="5dp" >

  <TextView
    android:id="@+id/song_title"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textColor="#FFFFFF99"
    android:textSize="20sp"
    android:textStyle="bold" />

  <TextView
    android:id="@+id/song_artist"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textColor="#FFFFFF99"
    android:textSize="18sp" />

</LinearLayout>

Не стесняйтесь изменять layout по своему вкусу. Каждая песня в списке будет представлена строками названия и артиста, поэтому мы будем использовать TextViews для отображения этих данных. Обратите внимание: в теге открытия LinearLayout указан атрибут onClick. Мы будем использовать этот метод в основном классе Activity, чтобы реагировать на выбор песни в списке, проигрывая песню, представленную элементом списка, который был выбран.

Шаг 3

Мы будем использовать Adapter для отображения песен в виде списка. Добавьте в приложение новый класс SongAdapter или назовите иначе. При создании класса назначьте ему суперкласс android.widget.BaseAdapter. Eclipse должен вставить следующую схему:

public class SongAdapter extends BaseAdapter {

  @Override
  public int getCount() {
    // TODO Auto-generated method stub
    return 0;
  }

  @Override
  public Object getItem(int arg0) {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public long getItemId(int arg0) {
    // TODO Auto-generated method stub
    return 0;
  }

  @Override
  public View getView(int arg0, View arg1, ViewGroup arg2) {
    // TODO Auto-generated method stub
    return null;
  }

}

Вам нужно будет добавить следующие imports:

import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import android.widget.TextView;

В объявлении класса задайте следующие переменные:

private ArrayList<Song> songs;
private LayoutInflater songInf;

Мы передадим список композиций из основного класса Activity и используем LayoutInflater для сопоставления строк заголовка и исполнителя с TextViews в созданном нами layout песни.

После переменных экземпляра придайте адаптеру метод конструктора для их создания:

public SongAdapter(Context c, ArrayList<Song> theSongs){
  songs=theSongs;
  songInf=LayoutInflater.from(c);
}

Измените содержимое метода getCount, чтобы вернуть размер списка:

@Override
public int getCount() {
  return songs.size();
}

Вы можете оставить методы getItem и getItemId нетронутыми. Обновите реализацию метода getView, как показано ниже:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
  //map to song layout
  LinearLayout songLay = (LinearLayout)songInf.inflate
      (R.layout.song, parent, false);
  //get title and artist views
  TextView songView = (TextView)songLay.findViewById(R.id.song_title);
  TextView artistView = (TextView)songLay.findViewById(R.id.song_artist);
  //get song using position
  Song currSong = songs.get(position);
  //get title and artist strings
  songView.setText(currSong.getTitle());
  artistView.setText(currSong.getArtist());
  //set position as tag
  songLay.setTag(position);
  return songLay;
}

Мы устанавливаем текст названия и исполнителя, выбирая правильный экземпляр Song из списка, используя индекс позиции, сопоставляя эти строки с представлениями, добавленными в файл макета песни. Мы также устанавливаем позицию в качестве тега вида, которая позволит нам играть правильную песню, когда пользователь нажимает на элемент в списке. Помните, что файл формата song.xml включал атрибут onClick. Мы будем использовать метод, указанный там, чтобы получить тег в Activity.

Шаг 3

Вернувшись в основной класс Activity, в методе onCreate после сортировки списка создайте новый экземпляр класса Adapter и установите его в ListView:

SongAdapter songAdt = new SongAdapter(this, songList);
songView.setAdapter(songAdt);

Когда вы запускаете приложение, оно должно отображать список песен на устройстве, щёлкнув по ним, приложение будет вызывать исключение на данный момент, но мы реализуем обработчик щелчка в следующем уроке.

Заключение

Теперь мы настроили приложение для чтения песен с пользовательского устройства. В следующей части мы начнем воспроизведение, когда пользователь выберет песню, используя класс MediaPlayer. Мы реализуем воспроизведение с использованием класса Service, чтобы оно продолжалось, пока пользователь занят другими приложениями. Наконец, мы будем использовать класс MediaController, чтобы дать пользователю управлять воспроизведением.

Время на прочтение
7 мин

Количество просмотров 6.7K

Мы продолжаем рассматривать разные платформенные применения Go (ранее мы посмотрели как использовать Go для микроконтроллеров, веб-приложений, разработки API, создания мобильных приложений) и сегодня поговорим об использовании Go для создания приложений для настольных компьютеров на примере реализации несложного mp3-плеера с поддержкой графического интерфейса. Мы будем использовать связывание с GTK для реализации интерфейса, библиотеки декодирования mp3 и взаимодействия с аудиосистемой (для Windows, Linux и MacOS).

Прежде всего начнем с того, что при компиляции Go финальным артефактом может быть исполняемый файл для Windows / Linux / MacOS. Поскольку на этапе связывания приложение может взаимодействовать с системными и прикладными библиотеками, разработанными для соответствующей операционной системы, мы можем использовать возможности кроссплатформенных графических библиотек (например, GTK) и библиотеки для подключения к аудиосерверам (например, pulseaudio или более новый pipewire). Начнем рассмотрение с изучения методов связывания С-библиотек и кода на Go:

Для примера создадим простую функцию на C, которая будет суммировать два числа и соответствующую обертку на Go для ее вызова (разместим в c/sum.c):

int sum(int a, int b) {
  return a+b;
}

Теперь в коде на Go добавим в комментарий импорт исходного текста на C (через директиву #include) и импортируем именованный пакет «C», в результате получим при компиляции экспортированные символы в псевдопакете C (наряду с другими функциями, например преобразования числа Go в целочисленную переменную C, для работы с указателями и др). Для вызова нашей функции создадим функцию-обертку на Go:

package main

/*
#include "c/sum.c"
*/
import "C"

import (
	"errors"
	"fmt"
)

func main() {
	fmt.Println("Hello, World!")
	val, _ := sum(1, 2)
	fmt.Printf("Sum: %dn", val)
}

func sum(a, b int) (int, error) {
	// val, _ := a+b, 0
	val, err := C.sum(C.int(a), C.int(b))
	if err != nil {
		return 0, errors.New("Error calling sum " + err.Error())
	}
	return int(val), nil
}

Наиболее важные функции из пакета С:

  • CString(str) — возвращает указатель на C-представление строки из Go

  • CBytes([]byte) — указатель на массив байт (в действительности на копию)

  • GoString(ptr) — преобразует C-строку в строку для Go

  • GoStringN(ptr, N) — преобразует C-строку с заданной длиной в строку Go

  • GoBytes(ptr, N) — последовательность байт длиной N для Go (тип []byte)

  • free(unsafe.Pointer(ptr)) — освобождение памяти под указателем (часто используется с defer), при подключении stdlib.h

Эти функции могут быть полезны при разработке собственных оберток вокруг динамических библиотек, а также для понимания принципов работы существующих go-модулей, которые используют внешние загружаемые библиотеки (например, GTK). При импорте можно использовать как файлы с исходными кодами, так и header-файлы (в этом случае будет использоваться связывание с библиотекой при сборке приложения).

Теперь посмотрим на реализацию связывания Go с библиотеками Gtk. Будем использовать проект https://github.com/gotk3/gotk3. Он предоставляет обертки вокруг GTK-функций и использует тот же подход компиляции через cgo, что и был рассмотрен ранее. Создадим простое окно на экране через использование этого пакета:

package main

import (
	"log"

	"github.com/gotk3/gotk3/gtk"
)

func main() {
	gtk.Init(nil)

	//новое окно
	win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
	if err != nil {
		log.Fatal("Unable to create window:", err)
	}
	win.SetTitle("MP3 Player")
	win.Connect("destroy", func() {
		//при событии закрытия окна отключаемся от gtk
		gtk.MainQuit()
	})

    ui(win)
	win.SetDefaultSize(400, 300)
	//отображение окна и запуск цикла событий
	win.ShowAll()
	gtk.Main()
}

func ui(win *gtk.Window) {
}

Наш mp3-проигрыватель будет принимать название файла как аргумент командной строки и отображать на окне одну кнопку — Play/Pause. Добавим кнопку в функцию ui:

func ui(win *gtk.Window) {
	button, _ := gtk.ButtonNew()
	button.Connect("clicked", func() {
		//toggle state
	})
	button_label, _ := gtk.LabelNew("Play/Pause")
	button.Add(button_label)
	win.Add(button)
}

Теперь добавим информацию об mp3-файле, для этого разделим окно по вертикали и в верхнюю часть будем отображать метку (создаем через gtk.LabelNew) с названием из метаданных mp3-файла. Для чтения метаданных будем использовать пакет github.com/bogem/id3v2. Добавим в импорты «github.com/bogem/id3v2/v2» и «os» для получения аргументов командной строки и прочитаем метаданные mp3:

func main() {
	mp3 := os.Args[1]
	tag, errid3 := id3v2.Open(mp3, id3v2.Options{Parse: true})
	if errid3 != nil {
		log.Fatalln("File not found or error in metadata extraction")
	}
//...
}

Также будем использовать построение с использованием сетки (gtk.Grid) и разместим кнопку под заголовок с названием из метаданных mp3 (каждый виджет будет занимать размер 1х1 элемент сетки):

func ui(win *gtk.Window, tag *id3v2.Tag) {
	layout, _ := gtk.GridNew()

	title, _ := gtk.LabelNew(tag.Title())
	layout.Attach(title, 0, 0, 1, 1) //верхний ряд

	button, _ := gtk.ButtonNew()
	button.Connect("clicked", func() {
		//toggle state
	})
	button_label, _ := gtk.LabelNew("Play/Pause")
	button.Add(button_label)
	//кнопка под меткой
	layout.AttachNextTo(button, title, gtk.POS_BOTTOM, 1, 1)
	win.Add(layout)
}

Теперь, когда мы имеем простой графический интерфейс, подключимся к аудиосерверу нашей операционной системы. Если мы используем Linux, то можно задействовать alsa, pulseaudio или pipewire (в зависимости от дистрибутива). MacOS используется интерфейс CoreAudio, для Windows — Windows Core Audio. Наиболее универсальным выглядят решения с использованием PortAudio (github.com/gordonklaus/portaudio) или библиотеки github.com/hajimehoshi/oto, которая позволяет воспроизводить звук на любой операционной системе (при этом для Windows и MacOS используется нативная реализация протокола, без cgo, в частности для MacOS будет присоединяться AudioToolbox.framework на этапе сборки исполняемого файла). В библиотеке oto для взаимодействия с аудиосервером используется Context, а для воспроизведения звука из декодированного аудиофайла — Players (создается из контекста).

Также от этого автора представлена библиотека декодирования mp3-файла, которая может взаимодействовать с библиотекой воспроизведения звука. Добавим необходимые импорты:

import (
...
    "github.com/hajimehoshi/go-mp3"
    "github.com/hajimehoshi/oto/v2"
)

Выполним инициализацию контекста и плеера (свяжем с mp3-файлом):

func initOto(file string) {
	log.Println("Loading mp3 from " + file)
	data, e1 := os.Open(file)
	if e1 != nil {
		log.Fatalln(e1.Error())
	}
	decodedStream, e2 := mp3.NewDecoder(data)
	if e2 != nil {
		log.Fatalln(e2.Error())
	}
	otoCtx, readyChan, e3 := oto.NewContext(44100, 2, 2)
	if e3 != nil {
		log.Fatalln(e3.Error())
	}
	//ждем завершения инициализации
	<-readyChan
	player = otoCtx.NewPlayer(decodedStream)
	loaded = true

	//сохраним объект для использования, пока окно открыто
	players := make([]oto.Player, 1, 1)
	players[0] = player
	runtime.KeepAlive(players)
}

Поскольку при воспроизведении будет нужно изменять надпись на кнопке (Play <—> Pause) перенесем объект метки для кнопки в глобальную переменную и реализуем логику запуска/приостановки воспроизведения:

var button_label *gtk.Label
var player oto.Player
var playing bool
var loaded bool

func ui(win *gtk.Window, tag *id3v2.Tag) {
	layout, _ := gtk.GridNew()

	title, _ := gtk.LabelNew(tag.Title())
	layout.Attach(title, 0, 0, 1, 1) //верхний ряд

	button, _ := gtk.ButtonNew()
	button.Connect("clicked", func() {
		if loaded {
			if playing {
				log.Println("Pause")
				player.Pause()
				button_label.SetLabel("Play")
			} else {
				log.Println("Play")
				player.Play()
				button_label.SetLabel("Pause")
			}
			playing = !playing
		}
	})
	button_label, _ = gtk.LabelNew("Play")
	button.Add(button_label)
	//кнопка под меткой
	layout.AttachNextTo(button, title, gtk.POS_BOTTOM, 1, 1)
	win.Add(layout)
}

После запуска (go run . test.mp3 или go build . && ./player test.mp3) появится окно с названием из метаданных mp3 и кнопкой «Play», при нажатии на которую начнется воспроизведение mp3-файла (кнопка будет заменена на Pause и будет приостанавливать воспроизведение). Однако, при завершении mp3-файла надпись на кнопке останется «Pause». Давайте это исправим, для этого мы будем отслеживать текущее состояние player.IsPlaying в goroutine и изменять соответствующие флаги и отображение на кнопке (добавим в конец initOto):

	go func() {
		playing = player.IsPlaying()
		for {
			if player.IsPlaying() != playing {
				playing = player.IsPlaying()
				if playing {
					button_label.SetLabel("Pause")
				} else {
					button_label.SetLabel("Play")
				}
			}
			time.Sleep(16 * time.Millisecond) //60fps
		}
	}()

и теперь в callback-функции для нажатия кнопки будем только управлять состоянием воспроизведения:

	button.Connect("clicked", func() {
		if loaded {
			if playing {
				log.Println("Pause")
				player.Pause()
			} else {
				log.Println("Play")
				player.Play()
			}
		}
	})

Теперь осталось добавить индикатор позиции воспроизведения. Текущее положение можно получить из объекта decodedStream, а полный размер потока (в байтах) через decodedStream.Length. Добавим индикатор (gtk.ProgressBar) на экран (в ui):

	progress, _ = gtk.ProgressBarNew()
	layout.AttachNextTo(progress, button, gtk.POS_BOTTOM, 1, 1)

в загрузке (после loaded=true): 

	lengthInBytes := decodedStream.Length()

в цикле проверки состояния:

			if playing {
				pos, _ := decodedStream.Seek(0, io.SeekCurrent)
				var fraction float64
				fraction = float64(pos) / float64(lengthInBytes)
				progress.SetFraction(fraction)
			}

Текущее положение также может быть получено в секундах (поскольку decodedStream это сырой поток несжатых данных, то одна секунда содержит 44100 * 2 * 2 байт). Также при установке нового положения нужно задавать смещение кратное 4 байтам (чтобы указывать на начало сэмпла). Последнее, что мы сделаем сейчас — возможность перемещения позиции воспроизведения при нажатии на индикатор положения. И здесь мы столкнемся с проблемой, что при регистрации callback-функции для контейнера будет получаться объект gdk.Event (внутри GTK это union, интерпретация которого зависит от типа события). В GDK библиотеке есть структура ButtonEvent, но из gdk.Event можно получить только Native представление структуры. Поэтому для извлечения координаты мыши при нажатии на элемент управления будем использовать unsafe.Pointer.

Сначала обернем виджет ProgressBar в контейнер EventBox и затем добавим обработчик события button-press-event через eventbox.Connect. Фрагмент функции ui может выглядить подобным образом:

	eventbox, _ := gtk.EventBoxNew()
	eventbox.Connect("button-press-event", func(widget *gtk.EventBox, event *gdk.Event) {
		allocation := widget.GetAllocation()
		width := allocation.GetWidth()
		//получаем координату X из структуры gdk.ButtonEvent
		x := *(*float64)(unsafe.Pointer(event.Native() + 24))
		//получаем долю общей продолжительности
		fraction := float64(x) / float64(width)
		//определяем смещение (с округлением до 4)
		offset := int64(float64(decodedStream.Length()) * fraction)
		offset = offset / 4 * 4 //align to sample
		//перемещаем воспроизведение на смещение
		player.(io.Seeker).Seek(offset, io.SeekStart)
		log.Println("Seek to fraction ", fraction)
	})
	progress, _ = gtk.ProgressBarNew()
	eventbox.Add(progress)
	layout.AttachNextTo(eventbox, button, gtk.POS_BOTTOM, 1, 1)

Мы создали простой проигрыватель MP3-файлов для desktop-операционных систем (Windows, Linux, MacOS) с использованием связываний на графическую библиотеку GTK и универсальные библиотеки для подключения к аудиосерверу. Разумеется, нужно предусмотреть также обработку ошибок, поддержку управления громкостью и многое другое, но основная задача была в рассмотрении принципов создания desktop-приложений с поддержкой мультимедиа в Go.

Исходный текст программы опубликован в github-репозитории.

GitHub — dzolotov/gomp3player: Simple Go + GTK MP3 Player

github.com

В заключение приглашаю всех на бесплатный урок курса Golang Developer, где разберем, что такое «дженерики» и как они нам могут помочь в ежедневных задачах. А также разберем, как они влияют на производительность и чем они лучше/хуже обычных интерфейсов.

  • Зарегистрироваться на бесплатный урок

Music Player Application Python Project

Everyone enjoys listening to music, therefore wouldn’t it be great to have our own MP3 player? So, in this python project, we’re going to use python and its libraries to make an mp3 player. Let’s get started on the mp3 player in Python project.

MP3 Music Player Application in Python Language

We’ll make an mp3 music player that allows us to play, stop, and restart tracks, as well as move from one song to the next and previous ones.

Python and associated libraries will be used. The first package we’ll use is Tkinter, a widely used GUI toolkit provided by Python. We don’t need to install it separately since it’s included with Python.

The mixer module of Pygame, a well-known Python library, will be used next.

Pygame is a programming language that is used to develop video games and contains graphics and sound libraries. One such sound library is Mixer. Then, to interface with the operating system, we’ll utilize Python’s os package.

Prerequisites for the Project

Working on a python mp3 player requires a basic familiarity of the Python programming language, tkinter, and the Pygame mixer module.

A basic grasp of Tkinter widgets is also necessary, but don’t worry, we’ll go through every line of code as we build this mp3 player project.

Unlike the Tkinter library, the Pygame library must be installed.

To install pygame, use the following line in your command prompt or terminal.

pip install pygame

Steps to take in order to complete this project

  • Import essential libraries
  • Make a project layout.
  • Define the functionality of the music player, such as play, pause, and other options.

Source Code for MP3 Music Player Application

#importing libraries 
from pygame import mixer
from tkinter import *
import tkinter.font as font
from tkinter import filedialog
#creating the root window 
root=Tk()
root.title('DataFlair Python MP3 Music player App ')
#initialize mixer 
mixer.init()
#create the listbox to contain songs
songs_list=Listbox(root,selectmode=SINGLE,bg="black",fg="white",font=('arial',15),height=12,width=47,selectbackground="gray",selectforeground="black")
songs_list.grid(columnspan=9)
#font is defined which is to be used for the button font 
defined_font = font.Font(family='Helvetica')
#play button
play_button=Button(root,text="Play",width =7,command=Play)
play_button['font']=defined_font
play_button.grid(row=1,column=0)
#pause button 
pause_button=Button(root,text="Pause",width =7,command=Pause)
pause_button['font']=defined_font
pause_button.grid(row=1,column=1)
#stop button
stop_button=Button(root,text="Stop",width =7,command=Stop)
stop_button['font']=defined_font
stop_button.grid(row=1,column=2)
#resume button
Resume_button=Button(root,text="Resume",width =7,command=Resume)
Resume_button['font']=defined_font
Resume_button.grid(row=1,column=3)
#previous button
previous_button=Button(root,text="Prev",width =7,command=Previous)
previous_button['font']=defined_font
previous_button.grid(row=1,column=4)
#nextbutton
next_button=Button(root,text="Next",width =7,command=Next)
next_button['font']=defined_font
next_button.grid(row=1,column=5)
#menu 
my_menu=Menu(root)
root.config(menu=my_menu)
add_song_menu=Menu(my_menu)
my_menu.add_cascade(label="Menu",menu=add_song_menu)
add_song_menu.add_command(label="Add songs",command=addsongs)
add_song_menu.add_command(label="Delete song",command=deletesong)
mainloop()
#add many songs to the playlist of python mp3 player
def addsongs():
    #to open a file  
    temp_song=filedialog.askopenfilenames(initialdir="Music/",title="Choose a song", filetypes=(("mp3 Files","*.mp3"),))
    ##loop through every item in the list to insert in the listbox
for s in temp_song:
        s=s.replace("C:/Users/DataFlair/python-mp3-music-player/","")
songs_list.insert(END,s)
     
def deletesong():
    curr_song=songs_list.curselection()
    songs_list.delete(curr_song[0])
    
    
def Play():
    song=songs_list.get(ACTIVE)
    song=f'C:/Users/lenovo/Desktop/DataFlair/Notepad/Music/{song}'
    mixer.music.load(song)
    mixer.music.play()
#to pause the song 
def Pause():
    mixer.music.pause()
#to stop the  song 
def Stop():
    mixer.music.stop()
    songs_list.selection_clear(ACTIVE)
#to resume the song
def Resume():
    mixer.music.unpause()
#Function to navigate from the current song
def Previous():
    #to get the selected song index
    previous_one=songs_list.curselection()
    #to get the previous song index
    previous_one=previous_one[0]-1
    #to get the previous song
    temp2=songs_list.get(previous_one)
                   temp2=f'C:/Users/DataFlair/python-mp3-music-player/{temp2}'
    mixer.music.load(temp2)
    mixer.music.play()
    songs_list.selection_clear(0,END)
    #activate new song
    songs_list.activate(previous_one)
    #set the next song
    songs_list.selection_set(previous_one)
def Next():
    #to get the selected song index
    next_one=songs_list.curselection()
    #to get the next song index
    next_one=next_one[0]+1
    #to get the next song 
    temp=songs_list.get(next_one)
            temp=f'C:/Users/DataFlair/python-mp3-music-player/{temp}'
    mixer.music.load(temp)
    mixer.music.play()
    songs_list.selection_clear(0,END)
    #activate newsong
    songs_list.activate(next_one)
     #set the next song
    songs_list.selection_set(next_one)

Output

Music plaayer python application

Summary

Congratulations! We have successfully developed a python mp3 music player, and we no longer need to depend on any other application.

We learnt a lot about python and its libraries via this project, the first of which was the Tkinter library, which is a widely-used GUI library with a variety of widgets, and then the essential mixer module of the pygame library, which is used to alter the music.

Music Player Application Python Project

Everyone enjoys listening to music, therefore wouldn’t it be great to have our own MP3 player? So, in this python project, we’re going to use python and its libraries to make an mp3 player. Let’s get started on the mp3 player in Python project.

MP3 Music Player Application in Python Language

We’ll make an mp3 music player that allows us to play, stop, and restart tracks, as well as move from one song to the next and previous ones.

Python and associated libraries will be used. The first package we’ll use is Tkinter, a widely used GUI toolkit provided by Python. We don’t need to install it separately since it’s included with Python.

The mixer module of Pygame, a well-known Python library, will be used next.

Pygame is a programming language that is used to develop video games and contains graphics and sound libraries. One such sound library is Mixer. Then, to interface with the operating system, we’ll utilize Python’s os package.

Prerequisites for the Project

Working on a python mp3 player requires a basic familiarity of the Python programming language, tkinter, and the Pygame mixer module.

A basic grasp of Tkinter widgets is also necessary, but don’t worry, we’ll go through every line of code as we build this mp3 player project.

Unlike the Tkinter library, the Pygame library must be installed.

To install pygame, use the following line in your command prompt or terminal.

pip install pygame

Steps to take in order to complete this project

  • Import essential libraries
  • Make a project layout.
  • Define the functionality of the music player, such as play, pause, and other options.

Source Code for MP3 Music Player Application

#importing libraries 
from pygame import mixer
from tkinter import *
import tkinter.font as font
from tkinter import filedialog
#creating the root window 
root=Tk()
root.title('DataFlair Python MP3 Music player App ')
#initialize mixer 
mixer.init()
#create the listbox to contain songs
songs_list=Listbox(root,selectmode=SINGLE,bg="black",fg="white",font=('arial',15),height=12,width=47,selectbackground="gray",selectforeground="black")
songs_list.grid(columnspan=9)
#font is defined which is to be used for the button font 
defined_font = font.Font(family='Helvetica')
#play button
play_button=Button(root,text="Play",width =7,command=Play)
play_button['font']=defined_font
play_button.grid(row=1,column=0)
#pause button 
pause_button=Button(root,text="Pause",width =7,command=Pause)
pause_button['font']=defined_font
pause_button.grid(row=1,column=1)
#stop button
stop_button=Button(root,text="Stop",width =7,command=Stop)
stop_button['font']=defined_font
stop_button.grid(row=1,column=2)
#resume button
Resume_button=Button(root,text="Resume",width =7,command=Resume)
Resume_button['font']=defined_font
Resume_button.grid(row=1,column=3)
#previous button
previous_button=Button(root,text="Prev",width =7,command=Previous)
previous_button['font']=defined_font
previous_button.grid(row=1,column=4)
#nextbutton
next_button=Button(root,text="Next",width =7,command=Next)
next_button['font']=defined_font
next_button.grid(row=1,column=5)
#menu 
my_menu=Menu(root)
root.config(menu=my_menu)
add_song_menu=Menu(my_menu)
my_menu.add_cascade(label="Menu",menu=add_song_menu)
add_song_menu.add_command(label="Add songs",command=addsongs)
add_song_menu.add_command(label="Delete song",command=deletesong)
mainloop()
#add many songs to the playlist of python mp3 player
def addsongs():
    #to open a file  
    temp_song=filedialog.askopenfilenames(initialdir="Music/",title="Choose a song", filetypes=(("mp3 Files","*.mp3"),))
    ##loop through every item in the list to insert in the listbox
for s in temp_song:
        s=s.replace("C:/Users/DataFlair/python-mp3-music-player/","")
songs_list.insert(END,s)
     
def deletesong():
    curr_song=songs_list.curselection()
    songs_list.delete(curr_song[0])
    
    
def Play():
    song=songs_list.get(ACTIVE)
    song=f'C:/Users/lenovo/Desktop/DataFlair/Notepad/Music/{song}'
    mixer.music.load(song)
    mixer.music.play()
#to pause the song 
def Pause():
    mixer.music.pause()
#to stop the  song 
def Stop():
    mixer.music.stop()
    songs_list.selection_clear(ACTIVE)
#to resume the song
def Resume():
    mixer.music.unpause()
#Function to navigate from the current song
def Previous():
    #to get the selected song index
    previous_one=songs_list.curselection()
    #to get the previous song index
    previous_one=previous_one[0]-1
    #to get the previous song
    temp2=songs_list.get(previous_one)
                   temp2=f'C:/Users/DataFlair/python-mp3-music-player/{temp2}'
    mixer.music.load(temp2)
    mixer.music.play()
    songs_list.selection_clear(0,END)
    #activate new song
    songs_list.activate(previous_one)
    #set the next song
    songs_list.selection_set(previous_one)
def Next():
    #to get the selected song index
    next_one=songs_list.curselection()
    #to get the next song index
    next_one=next_one[0]+1
    #to get the next song 
    temp=songs_list.get(next_one)
            temp=f'C:/Users/DataFlair/python-mp3-music-player/{temp}'
    mixer.music.load(temp)
    mixer.music.play()
    songs_list.selection_clear(0,END)
    #activate newsong
    songs_list.activate(next_one)
     #set the next song
    songs_list.selection_set(next_one)

Output

Music plaayer python application

Summary

Congratulations! We have successfully developed a python mp3 music player, and we no longer need to depend on any other application.

We learnt a lot about python and its libraries via this project, the first of which was the Tkinter library, which is a widely-used GUI library with a variety of widgets, and then the essential mixer module of the pygame library, which is used to alter the music.

  1. 1. Структура проекта
  2. 2. widget.ui
  3. 3. SimplePlayer.pro
  4. 4. widget.h
  5. 5. widget.cpp
  6. 6. Итог
  7. 7. Видеоурок

Предлагаю написать простенький аудио плеер для mp3 файлов с использованием Qt/C++, который будет иметь плейлист, возможность запуска/паузы/остановки треков, а также пролистывания треков.

Для реализации данной задумки в Qt имеются классы

QMediaPlayer

и

QMediaPlaylist,

которые относятся к модулю

multimedia.

А для отображения плейлиста воспользуемся

QStandardItemModel

и

QTableView.

Статьи данного цикла:

  • Кастомизация плеера в стиле AIMP

Структура проекта


  • SimplePlayer.pro

    — профайл проекта;

  • main.cpp

    — файл с функцией main;

  • widget.ui

    — файл формы окна приложения;

  • widget.h

    — заголовочный файл окна приложения;

  • widget.cpp

    — файл исходных кодов окна приложения;

  • buttons.qrc

    — ресурсный файл иконок кнопок приложения.

widget.ui

Интерфейс приложения сделаем с использованием графического дизайнера, и выглядеть он должен будет следующим образом.

В состав интерфейса приложения входят следующие элементы:


  • btn_add (QToolButton*)

    — отвечает за добавление треков в плейлист;

  • btn_next

    (QToolButton*)

    — отвечает за пролистывание плейлиста вперёд;

  • btn_previous (QToolButton*)

    — отвечает за пролистывание плейлиста назад;

  • btn_play (QToolButton*)

    — отвечает за воспроизведение трека;

  • btn_pause

    (QToolButton*)

    — отвечает за постановку трека на паузу;

  • btn_stop (QToolButton*)

    — отвечает за остановку трека;

  • currentTrack (QLabel*)

    — лейбл, в котором будет отображаться текущий трек;

  • playlistView (QTableView*)

    — таблица, отвечающая за отображение плейлиста.

SimplePlayer.pro

В профайле проекта не забудьте подключить модуль

multimedia,

иначе классы

QMediaPlayer

и

QMediaPlaylist

будут недоступны.

#-------------------------------------------------
#
# Project created by QtCreator 2016-06-29T11:25:56
#
#-------------------------------------------------

QT       += core gui multimedia

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = SimplePlayer
TEMPLATE = app


SOURCES += main.cpp
        widget.cpp

HEADERS  += widget.h

FORMS    += widget.ui

RESOURCES += 
    buttons.qrc

widget.h

Для реализации отображения плейлиста, придется использовать QStandardItemModel. В неё будут помещаться пути к аудио файлам, а также имена аудио файлов. В первой колонке будет имя аудио файла, а во второй будет полный путь, но данная колонка будет скрыта в объекте QTableView, который будет отвечать за отображение плейлиста.

Также пути к файлом в качестве медиа источников необходимо будет поместить в объект QMediaPlaylist, который будет помещён в QMediaPlayer.

Указатели на эти объекты помещаются в заголовочном файле окна приложения. Также здесь присутствует автогенерированый через дизайнер интерфейсов слот для обработки нажатия по кнопке добавления треков в плейлист.

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QStandardItemModel>
#include <QMediaPlayer>
#include <QMediaPlaylist>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_btn_add_clicked();              // Слот для обработки добавления треков через диалоговое окно

private:
    Ui::Widget *ui;
    QStandardItemModel  *m_playListModel;   // Модель данных плейлиста для отображения
    QMediaPlayer        *m_player;          // Проигрыватель треков
    QMediaPlaylist      *m_playlist;        // Плейлиста проигрывателя
};

#endif // WIDGET_H

widget.cpp

Для реализации плеера необходимо инициализировать объекты

QMediaPlayer, QMediaPlaylist

и

QStandardItemModel,

которые были объявлены в заголовочном файле окна приложения. В первой половине конструктора производится настройка внешнего вида таблицы для отображения плейлиста, тогда как во второй настройка самого плеера. Управление плеером осуществляется через кнопки, которые подключены к управляющим слотам

m_playlist

(для навигации) и

m_player

(для запуска/паузы/остановки).

При изменении текущего трека, плеер автоматически завершает воспроизведение того, трека который был до изменения, и запускает на воспроизведение новый трек.

В силу того, что

QMediaPlaylist

не имеет модели для отображения в таблице, мы воспользуемся классом

QStandardItemModel,

поэтому придётся добавлять данные о путях к файлам и туда, и туда.

#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QDir>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    // Настройка таблицы плейлиста
    m_playListModel = new QStandardItemModel(this);
    ui->playlistView->setModel(m_playListModel);    // Устанавливаем модель данных в TableView
    // Устанавливаем заголовки таблицы
    m_playListModel->setHorizontalHeaderLabels(QStringList()  << tr("Audio Track")
                                                            << tr("File Path"));
    ui->playlistView->hideColumn(1);    // Скрываем колонку, в которой хранится путь к файлу
    ui->playlistView->verticalHeader()->setVisible(false);                  // Скрываем нумерацию строк
    ui->playlistView->setSelectionBehavior(QAbstractItemView::SelectRows);  // Включаем выделение строк
    ui->playlistView->setSelectionMode(QAbstractItemView::SingleSelection); // Разрешаем выделять только одну строку
    ui->playlistView->setEditTriggers(QAbstractItemView::NoEditTriggers);   // Отключаем редактирование
    // Включаем подгонку размера последней видимой колонки к ширине TableView
    ui->playlistView->horizontalHeader()->setStretchLastSection(true);

    m_player = new QMediaPlayer(this);          // Инициализируем плеер
    m_playlist = new QMediaPlaylist(m_player);  // Инициализируем плейлист
    m_player->setPlaylist(m_playlist);          // Устанавливаем плейлист в плеер
    m_player->setVolume(70);                    // Устанавливаем громкость воспроизведения треков
    m_playlist->setPlaybackMode(QMediaPlaylist::Loop);  // Устанавливаем циклический режим проигрывания плейлиста

    // подключаем кнопки управления к слотам управления
    // Здесь отметим, что навигация по плейлисту осуществляется именно через плейлист
    // а запуск/пауза/остановка через сам плеер
    connect(ui->btn_previous, &QToolButton::clicked, m_playlist, &QMediaPlaylist::previous);
    connect(ui->btn_next, &QToolButton::clicked, m_playlist, &QMediaPlaylist::next);
    connect(ui->btn_play, &QToolButton::clicked, m_player, &QMediaPlayer::play);
    connect(ui->btn_pause, &QToolButton::clicked, m_player, &QMediaPlayer::pause);
    connect(ui->btn_stop, &QToolButton::clicked, m_player, &QMediaPlayer::stop);

    // При даблклике по треку в таблице устанавливаем трек в плейлисте
    connect(ui->playlistView, &QTableView::doubleClicked, [this](const QModelIndex &index){
        m_playlist->setCurrentIndex(index.row());
    });

    // при изменении индекса текущего трека в плейлисте, устанавливаем название файла в специальном лейбле
    connect(m_playlist, &QMediaPlaylist::currentIndexChanged, [this](int index){
        ui->currentTrack->setText(m_playListModel->data(m_playListModel->index(index, 0)).toString());
    });
}

Widget::~Widget()
{
    delete ui;
    delete m_playListModel;
    delete m_playlist;
    delete m_player;
}

void Widget::on_btn_add_clicked()
{
    // С помощью диалога выбора файлов делаем множественный выбор mp3 файлов
    QStringList files = QFileDialog::getOpenFileNames(this,
                                                      tr("Open files"),
                                                      QString(),
                                                      tr("Audio Files (*.mp3)"));

    // Далее устанавливаем данные по именам и пути к файлам
    // в плейлист и таблицу отображающую плейлист
    foreach (QString filePath, files) {
        QList<QStandardItem *> items;
        items.append(new QStandardItem(QDir(filePath).dirName()));
        items.append(new QStandardItem(filePath));
        m_playListModel->appendRow(items);
        m_playlist->addMedia(QUrl(filePath));
    }
}

Итог

После того, как приложение запустится, Вы сможете открыть mp3 треки и прослушать их.

Скачать Qt Audio Player

Видеоурок

Для создания проигрывателя, будем использовать элемент управления Media Player, который поддерживает следующие форматы:

— Advanced Streaming Format (ASF)
— Video On Demand (VOD)
— Moving Picture Experts Group 1,2,3 (MPEG 1,2,3)
— Real Audio (RA)
— Real Video (RV)
— Audio – Video Interleaved (AVI)
— Quick Time (MOV)
— Musical Instrument Digital Interface (MIDI)
— Indeo 5
— Waveform Audio (WAV)
— Sound File (SND)
— UNIX audio (AU)
— Audio Interchange File Format (AIFF)

Элемент управления Media Player представляет собой ActiveX, основывающийся на компоненте DirectShow уровня DirectX Media. Первое, что необходимо сделать, создать приложение на основе диалога с помощью мастера AppWizard.Следующий шаг, добавление к проекту элемента, делается это через «Project – Add To Project – Components and Controls»

Делаем свой mp3 проигрыватель на C++

Далее в появившемся окне открываем папку «Registered ActiveX Controls», находим ссылку «Windows Media Player.lnk» и жмем Insert

Делаем свой mp3 проигрыватель на C++

Нас спросят, хотим ли мы подключить компонент? Соглашайтесь. 🙂

После, откроется окно, где Вы можете поменять имена у подключаемых файлов. Когда компонент добавлен, в нашем проекте появится два новых файла. В них находится класс CMediaPlayer, который выполняет роль оболочки для элемента Media Player, а в редакторе ресурсов появится элемент Windows Media Player. Поместите его на свой диалог, в свойствах уберите галочку с пункта «Visible».

Теперь необходимо создать указатель с типом CMediaPlayer, в файле заголовке «ИмяВашегоПроектаDlg.h» напишите следующее:

Делаем свой mp3 проигрыватель

перед этим не забудьте добавить файл «mediaplayer.h»

Далее в инициализации диалога OnInitDialog() мы должны получить указатель на элемент Media Player, следующим способом:

m_pMediaPlayer = (CMediaPlayer *)GetDlgItem(IDC_MP);

Поместите на диалог кнопки с заголовками «Load…,Play,Pause,Stop» и Edit Box. В обработчике сообщения к кнопке «Load…» напишите:

CFileDialog m_dlg(TRUE,NULL,NULL,NULL,"MPEG Audio Files(*.mp3)|*.mp3|");
 
if (m_dlg.DoModal() == IDOK)
{
     m_pMediaPlayer->SetFileName(m_dlg.GetPathName());
     m_edit.SetWindowText(m_dlg.GetPathName());
}

Функция SetFileName() устанавливает файл который нужно воспроизвести. В Edit Box помещаем путь к файлу.
Обработчик сообщения кнопки «Play»: m_pMediaPlayer->Play();
Обработчик сообщения кнопки «Pause»: m_pMediaPlayer->Pause();
Обработчик сообщения кнопки «Stop»: m_pMediaPlayer->Stop();
m_pMediaPlayer->SetCurrentPosition(0); Данная функция устанавливает текущую точку воспроизведения.
Вот некоторые из наиболее часто используемых функций:
GetVolume() – получить значение громкости
SetVolume() – установить значение громкости
GetCurrentPosition() – получить текущую позицию воспроизведения
GetDuration() – возвращает длительность воспроизведения в секундах

Все теперь жмите F7 и Ваш собственный проигрыватель готов.

Сегодня я скомпилировал предыдущий код домашней работы на python и нашел несколько интересных мелочей, таких как следующие, около 70 строк кода, чтобы сделать простой музыкальный проигрыватель.

install some packages

pip install pygame

pygame — это кроссплатформенный модуль Python, разработанный специально для видеоигр, включая изображения и звуки.
Я в основном использую здесь Pygame для воспроизведения музыки. Есть два способа воспроизведения музыки в Pygame, такие как

music_one = pygame.mixer.Sound("test.mp3")
music_one.set_volume(0.05)
music_one.play()

pygame.mixer.music.load('test.mp3')
pygame.mixer.music.set_volume(0.05)
pygame.mixer.music.play()

Что касается эффекта, вышеупомянутые два метода одинаковы, небольшая разница в том, чтоpygame.mixer.Sound()
имеет возвращаемое значение иpygame.mixer.music.load()Нет, если нам нужно играть разную музыку в разных сценах в программе, возможно, даже в одно и то же время, мы не будем ее использоватьpygame.mixer.music.load(), Поскольку она похожа на глобальную переменную (это также может быть причиной того, что ее не нужно возвращать), последняя загрузка переопределит предыдущую загрузку, поэтому она подходит для воспроизведения фоновой музыки. иpygame.mixer.Sound()Существует возвращаемое значение, мы можем присвоить его переменной и использовать в сценах, где нужно проигрывать музыкуПеременная name.play ()Можно играть сразу.

Для более подробного использования pygame, такого как настройка параметров функции play (), обратитесь кофициальный учебник Pygame

pip install wxPython

Программирование на Python gui — более простая библиотека, поэтому я не буду много говорить.

Source codes

# -*- coding: utf-8 -*-
# автор: inpurer (Юэ Сяошуй Чанг)
# pc_type           lenovo
# create_date:      2018/12/1
# file_name:        test.py
 # описание: Юэ Xiaoshui долго, кровь не круто

import os
import pygame
import random
import wx

musicUrlList = []
 # Загрузить все .mp3 файлы в рабочий каталог
def musicUrlLoader():
	fileList = os.listdir(".")
	for filename in fileList:
		if filename.endswith(".mp3"):
			 печать («найти аудиофайл», имя файла)
			musicUrlList.append(filename)

class MyMusicPlayer(wx.Frame):
	def __init__(self,superion):
		wx.Frame.__init__(self,parent = superion, title = 'Xinspurer Player',size = (400,300))

		musicUrlLoader()

		MainPanel = wx.Panel(self)
		MainPanel.SetBackgroundColour('pink')

		 self.ShowInfoText = wx.StaticText (parent = MainPanel, label = 'Воспроизведение не началось', pos = (100,100)
										  ,size = (185,25),style = wx.ALIGN_CENTER_VERTICAL)
		self.ShowInfoText.SetBackgroundColour('white')

		 self.isPaused = False # Должно ли быть приостановлено
		 self.StartPlayButton = wx.Button (parent = MainPanel, label = 'Shuffle Play', pos = (100,150))
		self.Bind(wx.EVT_BUTTON, self.OnStartClicked, self.StartPlayButton)

		 self.PauseOrContinueButton = wx.Button (parent = MainPanel, label = 'Пауза воспроизведения', pos = (200,150))
		self.Bind(wx.EVT_BUTTON, self.OnPauseOrContinueClicked, self.PauseOrContinueButton)
		self.PauseOrContinueButton.Enable(False)

		pygame.mixer.init()



	def OnStartClicked(self,event):
		self.isPaused = False
		self.PauseOrContinueButton.Enable(True)

		self.willPlayMusic = random.choice(musicUrlList)
		pygame.mixer.music.load(self.willPlayMusic.encode())
		pygame.mixer.music.play()

		 self.ShowInfoText.SetLabel («Текущая игра:» + self.willPlayMusic)


	def OnPauseOrContinueClicked(self,event):
		if not self.isPaused:
			self.isPaused = True
			pygame.mixer.music.pause()
			 self.PauseOrContinueButton.SetLabel («Продолжить играть»)

			 self.ShowInfoText.SetLabel (воспроизведение приостановлено)
		else:
			self.isPaused = False
			pygame.mixer.music.unpause()
			 self.PauseOrContinueButton.SetLabel («Приостановить воспроизведение»)

			 self.ShowInfoText.SetLabel («Текущая игра:» + self.willPlayMusic)


if __name__ == "__main__":
	app = wx.App()
	myMusicPlayer = MyMusicPlayer(None)
	myMusicPlayer.Show()
	app.MainLoop()

Следует отметить, что для запуска кода необходимо поместить несколько песен .mp3 в текущий каталог.

Эффект бега


постскриптум

Весь код имеет последнее обновление на github:PythonLearning
Добро пожаловать на персональный публичный номер: вдохновитель

Понравилась статья? Поделить с друзьями:
  • Как написать программу для iphone на windows
  • Как написать программу для elm327
  • Как написать программу для 3д принтера
  • Как написать программу калькулятор на java
  • Как написать программу испытаний на изделие