Воспоминание мультимедия 18.02.2025
Всем привет! Хочу вспомнить про мультимедию. Будет от низкого уровня, до высокого уровня.
Будем сначало вспоминать на Си. на Embarcadero Dev-C++:
main.c:
#include <stdio.h> #include <windows.h> int main(int argc, char *argv[]) { /* Проигрывает аудиофайл с именем файла a_ja_pam_pam.wav синхронно, т.е. будет программа "висеть" пока не проиграет аудиофайл a_ja_pam_pam.wav */ sndPlaySound("a_ja_pam_pam.wav", SND_FILENAME | SND_SYNC); return 0; }
Но компилятор ошибку даст. Нужно добавить библиотеку libwinmm.a в проект, т.е. так: ../../Program Files (x86)/Embarcadero/Dev-Cpp/TDM-GCC-64/x86_64-w64-mingw32/lib/libwinmm.a
Теперь компилируем, и слышно как программа проигрывает аудиофайл a_ja_pam_pam.wav. После того как аудиофайл проиграет, наша программа завершается.
Если нужно чтобы проигралось ассинхронно, надо сделать вот так, вместо SND_SYNC заменим на SND_ASYNC:
main.c:
#include <stdio.h> #include <windows.h> int main(int argc, char *argv[]) { /* Проигрывает аудиофайл с именем файла a_ja_pam_pam.wav ассинхронно, т.е. будет программа "висеть" пока не проиграет аудиофайл a_ja_pam_pam.wav */ sndPlaySound("a_ja_pam_pam.wav", SND_FILENAME | SND_ASYNC); /* Специально нужна пауза, а то если выйдет из программы, звук перестанет проигрывать */ system("pause"); return 0; }
Теперь запустив, слышим как проигрывается аудиофайл a_ja_pam_pam.wav, если нажать любую клавишу, то программа выйдет, и звук перестанет проигрываться.
Продолжим вспоминать мультимедия.
Короче если нужно из ресурсов проиграть звуковой файл то нужно указать флаг SND_RESOURCE, вот пример:
#include <stdio.h> #include <windows.h> #include "resource.h" int main(int argc, char *argv[]) { /* Загружаем файл из ресурса IDR_WAVE1 */ PlaySound(MAKEINTRESOURCE(IDR_WAVE1),GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC); /* Специально нужна пауза, а то если выйдет из программы, звук перестанет проигрывать */ system("pause"); return 0; }
В низкий уровень программирования я ещё вернусь. А теперь речь пойдёт о высоком уровне. Для этого буду использовать функцию mciSendString. Эта функция т.е. mciSendString может не только звуковые файлы проигрывать но и аудио CD, видео, и даже DVD видео.
1. Создадим в Embarcadero Dev-C++ новый проект Windows Application и язык выберем C (т.е. Си).
2. Добавим в проект библиотеку ../../Program Files (x86)/Embarcadero/Dev-Cpp/TDM-GCC-64/x86_64-w64-mingw32/lib/libwinmm.a.
3. Вот код main.c:
#define VIDEO_ID "my_video" #include <windows.h> HWND hwndButton; HWND hwndStatic; char buf[1000]; LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { switch(Message) { case WM_COMMAND: sprintf(buf, "play %s", VIDEO_ID); mciSendString(buf, NULL, 0, 0); break; case WM_CREATE: hwndButton = CreateWindow("BUTTON", "Play", WS_CHILD | WS_VISIBLE, 10, 10, 100, 20, hwnd, (HMENU)NULL, NULL, lParam); hwndStatic = CreateWindow("STATIC", "", WS_CHILD | WS_VISIBLE, 10, 40, 800, 600, hwnd, (HMENU)NULL, NULL, lParam); sprintf(buf, "open \"movie.avi\" type MPEGVideo alias %s parent %ld style child", VIDEO_ID, (long)hwndStatic); mciSendString(buf, NULL, 0, 0); sprintf(buf, "put %s window at 10 10 320 240 225", VIDEO_ID); mciSendString(buf, NULL, 0, 0); break; case WM_DESTROY: { PostQuitMessage(0); break; } default: return DefWindowProc(hwnd, Message, wParam, lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG msg; memset(&wc,0,sizeof(wc)); wc.cbSize = sizeof(WNDCLASSEX); wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszClassName = "usw82_simple_media_player"; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed!","Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"usw82_simple_media_player", "Simple Media Player", WS_VISIBLE | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 840, 698, NULL, NULL, hInstance, NULL); if(hwnd == NULL) { MessageBox(NULL, "Window Creation Failed!","Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } while(GetMessage(&msg, NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
4. Вуаля! Вот наш проигрыватель, он проигрывает видео т.е. avi-файл. Это видео я сам делал в программе Blender 2.79.
Продолжим вспоминать. Вспоминать будем на Borland C++ Builder 4
Короче я за 2 минуты сделал простенький видео медиа плеер. В Borland C++ Builder 4 есть компонент MediaPlayer:
Видео где будет отображаться у меня называется Panel1, а компонент, который проигрывает видео называется MediaPlayer1:
Нужно сделать следующее - AutoEnable = true, AutoOpen = true, Display = Panel1, FileName=C:\Windows\Clock.avi, VisibleButtons - btRecord = false, btEject = false:
Вуаля! А вот и наш простенький медиа плеер, который может проигрывать видео файлы:
Марк Цукерберг когда ещё учился вроде бы создал музыкальный проигрыватель на обычном Visual Basic, назывался Synapse Media Player, вот так выглядкл этот медиаплеер - https://windows-cdn.softpedia.com/screenshots/Synapse-Medi.... Я когда был школьником тоже пытался создать свой медиа плеер, и даже свой кодек см. Воспоминания свой кодек на VB6, 15.05.2024. Сегодня или завтра попробую создать на Visual Basic DivX проигрыватель.
Я буду делать на каком-то из этих Visual Basic-ов. У меня тут Visual Basic 4 Enterprise Edition, Visual Basic 5 Enterprise Edition, Visual Basic 6 Professional Edition:
Предумываем свой скрипт. Короче в Visual Basic и VBA есть функция split. Эта функция расщепляет строку на массив, спомощью конкретного делителя. Допустим в нашем скрипте алгоритм такой КОМАНДА потом пробел и парметры, например INTRO startup.avi.
Команда |
Параметры |
Пример |
Описание |
INTRO |
имя_файла.avi |
INTRO startup.avi |
Запускается видео в самом начале |
MENU_BG |
имя_файла.jpeg |
MENU_BG mainmenu.jpeg |
Отображает картинку, которая служит менюшкой. |
MENU_AU |
имя_файла.mp3 |
MENU_AU mainmenu.mp3 |
Проигрывает аудио, пока находишься в меню. |
MOVIE |
имя_файла.avi |
MOVIE gladiator.avi |
Загружает видео, когда пользователь нажмёт на проигрывание, фильм запустится |
HOTSPOTS |
X, y, pos, x, y, pos, … |
HOTSPOTS 10 10 0, 10 40, 500 |
При нажатие на видео, загружается позиция видео |
Нужно сделать следующее - AutoEnable = true, AutoOpen = true, Display = Panel1, FileName=C:\Windows\Clock.avi, VisibleButtons - btRecord = false, btEject = false:
Главное забыл написать, нужно написать DeviceType=dtAVIVideo.
Тут опечатка:
Команда
Параметры
Пример
Описание
HOTSPOTS
X, y, pos, x, y, pos, …
HOTSPOTS 10 10 0, 10 40, 500
При нажатие на видео, загружается позиция видео
Правильно вот так:
Команда |
Параметры |
Пример |
Описание |
HOTSPOTS |
x y w h pos, x y w h pos, |
HOTSPOTS 10 10 100 20 0 |
При нажатие на видео, загружается позиция видео |
Вот так будем парзить:
Sub Main() Dim strCmd as String = "HOTSPOTS 10 10 100 20 0" Dim arrResult() as String Dim i as Integer arrResult = Split(strCmd, " ") For i = LBound(arrResult, 1) To UBound(arrResult, 1) MsgBox arrResult(i) Next i End Sub
Результат работы алгоритма:
HOTSPOTS 10 10 100 20 0
Короче я почти сделал проигрыватель, где-то приблизительно на это 2 часа потратил:
Код frmPlayer.frm:
VERSION 5.00 Begin VB.Form frmPlayer AutoRedraw = -1 'True BorderStyle = 1 'Fixed Single Caption = "DivX проигрыватель v1.0" ClientHeight = 570 ClientLeft = 45 ClientTop = 330 ClientWidth = 4290 LinkTopic = "Form1" MaxButton = 0 'False MinButton = 0 'False ScaleHeight = 570 ScaleWidth = 4290 StartUpPosition = 3 'Windows Default Begin VB.CommandButton cmdStop Caption = "Остановка" Height = 375 Left = 960 TabIndex = 2 Top = 120 Width = 975 End Begin VB.CommandButton cmdInfo Caption = "Информация о фильме" Height = 375 Left = 2040 TabIndex = 1 Top = 120 Width = 2175 End Begin VB.CommandButton cmdPlay Caption = "Пуск" Height = 375 Left = 120 TabIndex = 0 Top = 120 Width = 735 End End Attribute VB_Name = "frmPlayer" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = False Private Type DURATION hours As Integer minutes As Integer seconds As Integer End Type Dim bIsVideoOpened As Boolean Dim strYear As String Dim strTitle As String Dim strMoveFileName As String Dim strIntroFilename As String Dim strMenuImageFilename As String Dim strMenuBGMusic As String Dim durMovieDuration As DURATION Dim durBGAudioDuration As DURATION Private Sub ReadDisk() 'Const cStrCommand = "INTRO c:\divxplay\intro.avi" Dim strCmd As String Dim arrParams() As String Dim i As Integer 'Если видео уже проигрывается, то выходит If bIsVideoOpened = True Then Exit Sub bIsVideoOpened = True 'Показывает экран, на котором будет проигрываться видео frmMovieScreen.Show 'Открывает файл starutp.cfg Open "C:\divxplay2\startup.cfg" For Input As #1 'Пока файл незакрыт, читать данные Do While Not EOF(1) 'Читаем каждую строчку в файле Input #1, strCmd 'Если строчка не пустая, то запускается наш 'интерпретатор If strCmd <> "" Then 'Парзим строки, и разделяем команды и параметры Select Case GetCommand(strCmd) 'Фильм года Case "YEAR" If getParametersCount(strCmd) > 0 Then arrParams = GetParameters(strCmd) strYear = arrParams(0) End If 'Длительность фильма Case "MOVIEDURATION" Dim arrParamsMovieDuration() As String If getParametersCount(strCmd) > 0 Then arrParams = GetParameters(strCmd) arrParamsMovieDuration = Split(arrParams(1), ":") durMovieDuration.hours = CInt(arrParamsMovieDuration(0)) durMovieDuration.minutes = CInt(arrParamsMovieDuration(1)) durMovieDuration.seconds = CInt(arrParamsMovieDuration(2)) End If 'Длительность фоновой музыки Case "BGAUDIODURATION" Dim arrParamsBGAudioDuration() As String If getParametersCount(strCmd) > 0 Then arrParams = GetParameters(strCmd) arrParamsBGAudioDuration = Split(arrParams(1), ":") durBGAudioDuration.hours = CInt(arrParamsBGAudioDuration(0)) durBGAudioDuration.minutes = CInt(arrParamsBGAudioDuration(1)) durBGAudioDuration.seconds = CInt(arrParamsBGAudioDuration(2)) End If 'Название фильма Case "TITLE" If getParametersCount(strCmd) > 0 Then arrParams = GetParameters(strCmd) strTitle = arrParams(1) frmMovieScreen.Caption = arrParams(1) End If 'Интро, запускается при запуске фильма Case "INTRO" If getParametersCount(strCmd) > 0 Then arrParams = GetParameters(strCmd) strIntroFilename = arrParams(1) End If 'Картинка для менюшки Case "MENU_BG" If getParametersCount(strCmd) > 0 Then arrParams = GetParameters(strCmd) strMenuImageFilename = arrParams(1) End If 'Музыка во время запуска меню Case "MENU_AU" If getParametersCount(strCmd) > 0 Then arrParams = GetParameters(strCmd) strMenuBGMusic = arrParams(1) End If 'Устанавливает видео Case "MOVIE" If getParametersCount(strCmd) > 0 Then arrParams = GetParameters(strCmd) strMoveFileName = arrParams(1) End If 'Для меню Case "HOTSPOTS" If getParametersCount(strCmd) > 0 Then arrParams = GetParameters(strCmd) End If End Select End If Loop End Sub Private Sub cmdInfo_Click() 'Показывает информацию о CD диске If bIsVideoOpened = True Then MsgBox "Название фильма:" & strTitle & vbCrLf _ & "Год:" & strYear & vbCrLf _ & "Длительность фильма:" & CStr(durMovieDuration.hours) _ & "часов(а), " & CStr(durMovieDuration.minutes) _ & " минут, " & CStr(durMovieDuration.seconds) _ & " секунд " _ , vbInformation End If End Sub Private Sub cmdPlay_Click() 'Считываем файл startup.cfg ReadDisk End Sub Private Sub Form_Load() 'Инициализация strYear = "" strMoveFileName = "" strIntroFilename = "" strMenuImageFilename = "" strMenuBGMusic = "" strTitle = "" durBGAudioDuration.hours = 0 durBGAudioDuration.minutes = 0 durBGAudioDuration.seconds = 0 durMovieDuration.hours = 0 durMovieDuration.minutes = 0 durMovieDuration.seconds = 0 'Закрывает видео CloseVideo "vid1" bIsVideoOpened = False End Sub Private Sub Form_Unload(Cancel As Integer) 'Если окно закрывается If bIsVideoOpened = True Then 'То закрыть видео CloseVideo "vid1" End If 'Закрыть экран, но котором будет проигрывать видео Unload frmMovieScreen End Sub
Код modMain.bas:
Attribute VB_Name = "modMain" Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 'Возвращает количество параметров в команде Public Function getParametersCount(ByVal strCmd As String) As Integer Dim arrResult() As String 'Пробелом отделяются параметры от команды. 'Функция Split расщепляет строку спомощью делителя, 'а если быть точнее делитель у нас пробел. arrResult = Split(strCmd, " ") 'Возвращает количество параметров getParametersCount = UBound(arrResult, 1) End Function 'Возвращает названия команды Public Function GetCommand(ByVal strCmd As String) As String Dim arrResult() As String 'Пробелом отделяются параметры от команды. 'Функция Split расщепляет строку спомощью делителя, 'а если быть точнее делитель у нас пробел. arrResult = Split(strCmd, " ") GetCommand = arrResult(LBound(arrResult, 1)) End Function 'Возвращает параметры Public Function GetParameters(ByVal strCmd As String) As String() Dim arrResult() As String Dim strCmdNew As String Dim i As Integer 'Пробелом отделяются параметры от команды. 'Функция Split расщепляет строку спомощью делителя, 'а если быть точнее делитель у нас пробел. arrResult = Split(strCmd, " ") 'Отсекам команду strCmdNew = Mid(strCmd, Len(arrResult(0)) + 1, Len(strCmd)) 'Если параметров больше чем один, то: If getParametersCount(strCmdNew) > 1 Then 'Пробелом отделяются параметры от команды. 'Функция Split расщепляет строку спомощью делителя, 'а если быть точнее делитель у нас пробел. arrResult = Split(strCmdNew, " ") 'Возвращаем массив параметро GetParameters = arrResult Else ' Если только один параметр, то возвращет массив с одним параметром arrResult(0) = strCmdNew GetParameters = arrResult End If End Function
Код modMCI.bas:
Attribute VB_Name = "modMCI" 'API Функция нужна для проигрывание мультимедийных файлов Public Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" _ (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, _ ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long 'Открывает видео Public Sub OpenVideo(ByVal strFileName, _ ByVal strAlias As String, _ ByVal lngHwnd As Double) Dim strCmd As String Dim lpStrReturnValue As String Dim lngLength As Integer strCmd = "open """ & strFileName _ & """ type MPEGVideo alias " _ & strAlias _ & " parent " & CStr(lngHwnd) & " style child" mciSendString strCmd, lpStrReturnValue, lngLength, lngHwnd strCmd = "put " & strAlias & " window at 10 10 320 240 225" mciSendString strCmd, lpStrReturnValue, lngLength, lngHwnd End Sub 'Проигрывает видео Public Sub PlayVideo(ByVal strAlias As String) Dim strCmd As String Dim lpStrReturnValue As String Dim lngLength As Integer strCmd = "play " & strAlias mciSendString strCmd, lpStrReturnValue, lngLength, lngHwnd End Sub 'Закрывает видео Public Sub CloseVideo(ByVal strAlias As String) Dim strCmd As String Dim lpStrReturnValue As String Dim lngLength As Integer strCmd = "stop " + strAlias mciSendString strCmd, lpStrReturnValue, lngLength, lngHwnd strCmd = "close " + strAlias mciSendString strCmd, lpStrReturnValue, lngLength, lngHwnd End Sub
Пример startup.cfg:
TITLE Гладиатор YEAR 2000 MOVIEDURATION 01:01:01 INTRO intro.avi MENU_BG menu.bmp MENU_AU menu.mp3 MOVIE gladiator.avi HOTSPOTS 0 0 0 0 0 0 0 0 0 0 0 0