Інтерфейс управління пристроями MCI (Media Control Interface), Різне, Програмування, статті

Інтерфейс управління пристроями MCI (Media Control Interface) Дозволяє програмам для Windows працювати з різними пристроями мультимедіа які включають в себе CD-ROM, звукову карту, програвач відеодисків, навіть відеомагнітофон і т.д. За допомогою функцій MCI ми можемо управляти вище перерахованими пристроями, посилаючи їм спеціальні команди такі як: відтворення, зупинка, відтворення із заданою позиції і т.д.

Конкретний набір команд відповідає кожному пристрою свій. Цю команду ми передаємо у функцію інтерфейсу MCI.


Всі функції інтерфейсу MCI починаються з префікса mci і діляться на три групи:



Дві функції високого рівня – mciSendCommand() і mciSendString() виконують одну й ту ж саму функцію. Відмінність між ними полягає у способі подачі команд.


Першу функцію, яку ми розглянемо буде mciSendCommand(). Вона описується наступним чином:

DWORD mciSendCommand(MCIDEVICEID IDDevice,
UINT uMsg,
DWORD fdwCommand,
DWORD dwParam)

де:



Якщо функція повертає 0, то все в повному порядку. У випадку помилки функція повертає код помилки. Сам код помилки знаходиться в молодшому байті слова, а в старшому, де мав би знаходиться код нашого пристрою, буде 0.


Слід акцентувати Вашу увагу на четвертому параметрі цієї функції. Різні команди користуються різними наборами вихідних даних. Перед тим як викликати функцію, ми повинні заповнити структуру даними, необхідними для виконання тільки одного потрібної нам команди.


Що ж представляє із себе функція mciSendString() ?
Ось її опис:

DWORD mciSendString(LPTSTR lpszCommand,
LPTSTR lpszReturnString,
UINT cchReturn,
HANDLE hwndCallback)

де:



Отже, функція повертає 0 в разі успіху і, відповідно, код помилки в іншому лучан. За допомогою коду помилки можна отримати додаткову інформацію. Це відноситься і до mciSendCommand()! Не плутайте це з параметром lpszReturnString, Він просто зберігає інформацію про те, яку роботу виконує дана функція.


Ось маленький прімерчік: відтворення wave-файла.

#include “stdafx.h”
#include <mmsystem.h>

void main()
{
DWORD result = mciSendString(“play c:windowsmedia ada.wav wait”, NULL, 0, NULL);
if (result)
printf (“Помилка”);
}


Необхідно додати бібліотеку winmm.lib ! Інакше “пролетить”!


Обробка помилок


Як вже було сказано, функції MCI повертають код помилки при невдалому їх виконання. І тутже виникає питання: “а куди, власне, подіти цей код?”. Тут нам на допомогу приходить інша функція – mciGetErrorString(), Яка за кодом помилки виводить її текстовий опис. Ось як вона виглядає:

BOOL mciGetErrorString(DWORD fdwError,
LPTSTR lpszErrorText,
UINT cchErrorText)

де:



Як і більшість функцій, вона теж повертає результат своєї діяльності. Якщо вона повернула TRUE, То можна розслабитися і подивитися, що ж накоїла функція знаходиться перед нею. Інакше (FALSE) Доведеться поднопрячь звивини, тому що наша функція не змогла визначити причину виникнення помилки.


Давайте розглянемо конкретний приклад, де все встане на свої місця.

#include “stdafx.h”
#include <mmsystem.h>

void main()
{
const int cchErrorText = 128;
char lpszErrorText[cchErrorText];
DWORD fdwError = mciSendString(“play c:windows ada.wav wait”, NULL, 0, NULL);
if (fdwError)
{
BOOL dummy = mciGetErrorString(fdwError, lpszErrorText, cchErrorText);
if (dummy)
printf(“%s
“, lpszErrorText);
else
printf (“напряги звивини :-)”);
}
}


Я спеціально вказав невірний шлях до файлу, щоб спрацювала наша функція. Все дуже просто … правда?


Розглянемо деякі можливості функції mciSendString() в роботі з пристроями. Для прикладу візьмемо CD-ROM і знову повернемося до команди play. Як раніше я говорив, командний рядок можна розділити на три під команди: сама команда, пристрій, який будемо використовувати і параметри. Т.к. ми використовуємо команду play, То їй характерні, тільки для CD-ROM“А, два параметри: from position і to position. Під position мається на увазі передане значення, в даному випадку, для нашого пристрою, це будуть мінути.секунди.


За допомогою цих значень можна відтворювати трек з будь-якого тимчасового інтервалу. Параметр from задає початок відтворення, а to, Відповідно, його кінець.


Отже, розглянемо приклад. Припустимо трек буде програватися 7 хвилин 22 секунди, як увертюра “The Magic Flute“У Моцарта. А нам треба, що б програвався його шматочок: скажімо з 4 хвилин до 5 хвилин.

#include “stdafx.h”
#include <mmsystem.h>

void main()
{
char lpstrCommand[256];

/ / Задаємо інтервал часу
char lpszPlayFlags[] = “from 4 to 5”;
/ / Компонуємо командний рядок, де cdaudio – ідентифікатор пристрою
wsprintf(lpstrCommand, “play %s %s %s”, “cdaudio”, lpszPlayFlags, “wait”);
/ / Без коментарів
mciSendString(lpstrCommand, NULL, 0, NULL);
}


Слід трохи поекспериментувати, щоб зрозуміти “принцип роботи” цих параметрів.


digitalvideo


Продовжуємо використовувати команду play ! На цей раз ми будемо працювати з відео. Все, напевно, знають таку програму, як універсальний програвач. Ви можете подивитися скільки форматів вона може відтворювати, це вражає, а також вражає те, що всі ці формати реалізовані в самій ОС, і Ви можете цим скористатися! Як вже ви здогадалися мова піде про digitalvideo – Цифрове відео.


Ось список реалізованих параметрів:



Код програми я наводити не буду, тому що за основу Ви можете взяти програмку з 3 кроки, Де за місце пристрої cdaudio Ви повинні вказати шлях до відеофайлу (природно в лапках!), І поекспериментувати. Додатково хочу сказати, що dat-Файли ця програмка теж програє.


mciSendCommand () і CD-ROM


Крім функції mciSendString(), Ми згадували функцію mciSendCommand(). І зараз нею конкретно займемося. Цей проект буде досить насичений, так що тримайтеся. Пристрій виберемо найпоширеніше – CD-ROM.


Насамперед, перш ніж скористатися пристроєм, нам треба його відкрити (це логічно), тобто дізнатися його ID. Нам знадобиться для цього структура MCI_OPEN_PARMS:

typedef struct {
DWORD dwCallback;
MCIDEVICEID wDeviceID;
LPCTSTR lpstrDeviceType;
LPCTSTR lpstrElementName;
LPCTSTR lpstrAlias;
} MCI_OPEN_PARMS;

де:



Після того, як ми дізналися ідентифікатор пристрою наступним дією слід перевірити його на готовність. Для цього ми використовуємо структуру MCI_STATUS_PARMS:

typedef struct {
DWORD dwCallback;
DWORD dwReturn;
DWORD dwItem;
DWORD dwTrack;
} MCI_STATUS_PARMS;

де:



Ця структура використовується досить часто. Скоро Ви в цьому переконаєтеся.


Далі ми будемо збирати інформацію про диск. Для початку дізнаємося скільки треків на ньому міститься, потім довжину кожного треку (це нам знадобитися, щоб визначити його тривалість у хвилинах і секундах) і, природно, перевірити тип треку, тобто яку інформацію він несе: цифрову або аудіо. І на закінчення визначити тривалість кожного треку.


Почнемо з першого пункту. Відкриваємо наш пристрій:

 / / Оголошуємо структуру 
MCI_OPEN_PARMS mciOpenParms;

/ / Надаємо значення типу пристрою
mciOpenParms.lpstrDeviceType = “cdaudio”;

/ / Встановлюємо прапори, які вкажуть інтерфейсу, як потрібно
/ / Інтерпретувати інформацію в структурі mciOpenParms.
/ / В даному випадку ми повідомляємо MCI про те, що передаємо йому тип
/ / Пристрої.
DWORD flags = MCI_OPEN_TYPE;

/ / Давайте розглянемо, як ця функція буде використовувати ту
/ / Інформацію, яку ми заклали. Почнемо з першого параметра – 0.
/ / Так як ми не знаємо ще ідентифікатор нашого пристрою, тому
/ / Просто встановлюємо його в 0. Другий параметр говорить MCI, що ми
/ / Хочемо відкрити пристрій, ім’я якого вона витягне із структури
/ / MciOpenParms. З приводу третього параметра дивіться вище. І,
/ / Нарешті, останнім параметром нашої функції буде покажчик на
/ / Структуру з якої вона витягне необхідні їй дані. В даному
/ / Випадку, як я вже говорив, ім’я пристрою.

DWORD resume = mciSendCommand(0, MCI_OPEN, flags,
(DWORD) (LPVOID)& mciOpenParms);

/ / Якщо все було в порядку, отримуємо ідентифікатор пристрою
if (resume == 0)
wDeviceID = mciOpenParms.wDeviceID;


Наступне, що ми повинні зробити за списком, це перевірити пристрій на готовність:

 / / Т.к. ми опитуємо пристрій, то заповнюємо відповідний
/ / Елемент структури MCI_STATUS_PARMS – dwItem. Прапор
/ / MCI_STATUS_READY якраз і визначає пристрій на готовність.
mciStatusParms.dwItem = MCI_STATUS_READY;

/ / В якості першого параметра передаємо ідентифікатор пристрою.
/ / Другий параметр – це команда, яка пов’язана зі структурою
/ / MCI_STATUS_PARMS і яка витягує інформацію про пристрій.
/ / Третій параметр, навіть не знаю як сказати … підтверджує те,
/ / Що інформація, якою ми заповнили структуру, ставитися
/ / Тільки до властивостей пристрою. Ну і останнім параметром ми
/ / Передаємо покажчик на структуру MCI_STATUS_PARMS.
mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM,
(DWORD)& mciStatusParms);


Якщо пристрій у нас готове, то переходимо до третього пункту. Дізнаємося кількість треків. Код я наводити не буду, тому що далі все йде по аналогії. Знову ми хочемо отримати цікаву для нас інформацію. За цього будемо продовжувати використовувати структуру MCI_STATUS_PARMS, Тільки команда у нас поміняється і стане MCI_STATUS_NUMBER_OF_TRACKS, Яку ми відправимо в dwItem.


Тепер давайте визначимо довжину кожного треку. Як я вже говорив це нам потрібно, що б дізнатися час програвання треку. Для того, щоб визначити довжину, наприклад n-ого треку, нам слід звернутися по номеру цього треку. Як Ви вже здогадалися цей номер ми помістимо в dwTrack структури MCI_STATUS_PARMS, А команду визначення довжини треку –MCI_STATUS_LENGTH в dwItem. Тут ми вже почали працювати безпосередньо з треками, і я прошу акцентувати вашу увагу на третьому пераметре функції mciSendCommand(). В цьому випадку необхідно до прапора MCI_STATUS_ITEM додати ще й прапор MCI_TRACK. Це дуже важливо.


Перевіримо інформацію про тип треку. Записуємо номер треку в dwTrack, а в dwItam команду перевірки треку – MCI_CDA_STATUS_TYPE_TRACK. Після витягаємо зі структури результат, який зберігатиметься в dwReturn і порівнюємо з MCI_CDA_TRACK_AUDIO. Якщо значення рівні, то трек до якого ми звернулися несе аудіо інформацію.


І останнє, що нам залишилося – це визначити час програвання треків. Для цього скористаємося функціями MCI_MSF_MINUTE() і MCI_MSF_SECOND(). Переданим значенням є довжина треку.


“Виконання бажань” команда MCI_SET


Продовжуємо мучити наш CD-ROM. Тепер він буде безпосередньо виконувати наші команди. Команди ці самі різні такі як пауза, відтворення, зупинка, відкриття і закриття, запис і перехід на інший трек. А почнемо ми природно з самого примітивного – відкриття і закриття. Для установки управління пристрої використовується команда MCI_SET з належної їй структурою MCI_SET_PARMS. Ця команда повідомляє MCI, Що пристрій має виконати якусь дію, а що воно повинно виконати повідомляється третьому параметрі функції. У наведеному прикладі виконується команда відкриття CD, а щоб його закрити потрібно поміняти MCI_SET_DOOR_OPEN на MCI_SET_DOOR_CLOSED.


Приклад:

mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN,
(DWORD)& mciSetParms);

Спробуйте тепер це поєднати з попереднім проектом (CDPlayer).


MCI Play&Stop


Розглянемо приклад відтворення CD-треків.

mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF; 
flags = MCI_SET_TIME_FORMAT;
mciSendCommand(wDeviceID, MCI_SET, flags, (DWORD)& mciSetParms);

Першим ділом встановлюємо формат часу. Використовуємо вже знайому структуру – MCI_SET_PARMS, В якій встановлюємо параметр MCI_FORMAT_TMSF. Він говорить про те, що формат часу встановлюється в треках, хвилинах, секундах і фреймах. Як прапора передаємо прапор параметра часу – MCI_SET_TIME_FORMAT. Ну, а далі запускаємо нашу функцію.


Для того, щоб відтворити трек необхідно скористатися командою MCI_PLAY, Яка залежить від структури MCI_PLAY_PARMS. Ось її опис:

typedef struct { 
DWORD dwCallback;
DWORD dwFrom;
DWORDdwTo;
} MCI_PLAY_PARMS;

Де



Після того коли ми встановили формат часу, в якому буде відтворюватися трек, наступне що нам треба дізнатися, це довжину трека по якому в подальшому ми визначимо початок і кінець відтворення. Ось приклад коду:

 / / Визначаємо довжину трека через вже “готову” 
/ / Функцію, де track – це номер трека
DWORD lengthTrack = LengthTrack(track);

/ / За допомогою функції MCI_MAKE_TMSF задамо початок і кінець
/ / Відтворення скориставшись структурою MCI_PLAY_PARMS.
mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0);
mciPlayParms.dwTo = MCI_MAKE_TMSF(track,
MCI_MSF_MINUTE(lengthTrack),
MCI_MSF_SECOND(lengthTrack),
MCI_MSF_FRAME(lengthTrack));

/ / Задамо потрібні прапори
flags = MCI_FROM / MCI_TO;

/ / Почнемо відтворення
mciSendCommand(wDeviceID, MCI_PLAY, flags, (DWORD)& mciPlayParms);


При використанні прапорів MCI_FROM і MCI_TO необхідно встановлювати формат часу, як ми це зробили на початку цього вправи.


Тепер пора розглянути іншу команду – MCI_STOP (Коментарів я думаю не треба). Діємо за аналогією з командами відкриття та закриття CD.

mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)& mciGenericParms);

Це все, що потрібно зробити.


Програвання WAV файлу з пам’яті

> Hello ig,
> Допоможіть розібратися з таким питанням
> Необхідно програти фрагмент з. Wav файлу
> Я прочитав його в буфер
> char pbuf[100];
> UINT nBytesRead = cfile.Read( pbuf, 100 );
> Як я можу програти його за допомогою PlaySound
>
> —

На жаль, змушений розчарувати, в такому вигляді нічого не вийде. В принципі, PlaySound дійсно може програвати wav-И з пам’яті, але при цьому мається на увазі, що зображення звуку в пам’яті має правильний формат (тобто забезпечено заголовком із зазначенням формату, потім слідує власне блок даних і т.д.). То-якщо ти прочитаєш wav-Файл в пам’ять ФРАЗА, то він чесно програється командою:

PlaySound( pbuf, NULL, SND_MEMORY );

але якщо в буфері знаходиться лише частина файлу, функція видасть помилку, оскільки ця частина має “неправильний” формат.


Одне з рішень – використання MCI функцій. Як приклад приведу працює шматок з програми (я його кілька спростив для прикладу):

MCIERROR mciError;
MCI_OPEN_PARMS mciOpenParms;

mciOpenParms.lpstrDeviceType = “waveaudio”;
mciOpenParms.lpstrElementName = “sound38.wav”;
if (mciError = mciSendCommand(0, MCI_OPEN,
MCI_OPEN_TYPE / MCI_OPEN_ELEMENT,
(DWORD)(LPMCI_OPEN_PARMS)&mciOpenParms))
{
AfxMessageBox(“Can”t open”);
} else {
MCIDEVICEID mciDeviceID;
mciDeviceID = mciOpenParms.wDeviceID;
MCI_PLAY_PARMS mciPlayParms;
mciPlayParms.dwFrom = 300;
mciPlayParms.dwTo = 600;
if (mciError = mciSendCommand(mciDeviceID, MCI_PLAY,
MCI_FROM / MCI_TO / MCI_WAIT, (DWORD)(LPMCI_PLAY_PARMS)&mciPlayParms))
{
AfxMessageBox(“Can”t play”);
}
if (mciError = mciSendCommand(mciDeviceID, MCI_CLOSE, NULL, NULL))
{
AfxMessageBox(“Can”t close”);
}
}


Де:


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*