Inicializace CD-ROM
Aby bylo možné přehrávat hudbu z CD, je nejprve nutné ve funkci SDL_Init() zapnout symbolickou konstantou SDL_INIT_CDROM podporu CD mechanik. Tím je de facto základní inicializace hotová a může se přistoupit k vlastnímu programování.
Dále se musí položit dotaz, je-li v počítači vůbec nějaká CD mechanika, bez ní to opravdu nepůjde :-]. Funkce SDL_CDNumDrives() poskytuje jejich celkový počet, a pokud je nutné zjistit také systémová jména, lze použít SDL_CDName(). Za parametr se jí předávají čísla z rozsahu od nuly do počtu všech mechanik a vrací ukazatel na řetězec, jako je /dev/cdrom, D:\ apod. Jedná se pouze o informativní hodnotu.
int SDL_CDNumDrives(void);
const char *SDL_CDName(int drive);
Mechanika s daným pořadovým číslem, nultá je defaultní v systému, se otevře funkcí SDL_CDOpen(). Návratová hodnota představuje ukazatel na objekt struktury SDL_CD, které se budeme podrobně věnovat níže. Identifikátor se po skončení práce uvolňuje funkcí SDL_CDClose().
SDL_CD *SDL_CDOpen(int drive);
void SDL_CDClose(SDL_CD *cdrom);
Poslední otevřená mechanika se stane v aplikaci defaultní. To znamená, že se na ni lze při volání funkcí odkazovat argumentem NULL, který je předán místo identifikátoru SDL_CD.
Informace o CD
Po vložení CD do mechaniky je nutné funkcí SDL_CDStatus() aktualizovat obsah CD_ROM struktury.
CDstatus SDL_CDStatus(SDL_CD *cdrom);
Návratová hodnota poslouží pro získání stavových informací. Je jí výčtový typ, který může nabývat hodnot CD_TRAYEMPTY, CD_STOPPED, CD_PLAYING, CD_PAUSED a CD_ERROR. SDL také poskytuje makro CD_INDRIVE() podávající informaci, zda je v mechanice nějaký disk.
#define CD_INDRIVE(status) ((int)status > 0)
// Použití
if(CD_INDRIVE(SDL_CDStatus(cdrom)))
ZacniPrehravat();
Struktura SDL_CD jednoznačně identifikuje otevřenou CD mechaniku a také podává informace o disku, který je do ní vložený. První dvě položky jsou dostupné obecně, ostatní jsou validní pouze s CD. Aktuálnost obsahu je dána posledním voláním funkce SDL_CDStatus().
typedef struct
{
int id; // Privátní identifikátor
CDstatus status; // Stavové informace
int numtracks;
int cur_track;
int cur_frame;
SDL_CDtrack track[SDL_MAX_TRACKS+1];
} SDL_CD;
CD je obecně organizováno do jedné nebo více stop (v angličtině track), v naprosté většině případů je v každé z nich uložena jedna skladba. Stopy se dále skládají z určitého počtu framů, což jsou bloky dat o velikosti cca. 2 kB, které představují základní stavební jednotky CD. Při normální rychlosti se za jednu sekundu přehraje 75 framů. Tato hodnota je v SDL definována jako symbolická konstanta CD_FPS.
Numtracks uchovává počet stop na disku, cur_track obsahuje číslo aktuálně přehrávané stopy a cur_frame číslo přehrávaného framu ve stopě. Samozřejmě nesmí chybět ani pole stop. Jeho velikost je definována staticky konstantou SDL_MAX_TRACKS rovnající se 99.
Struktura SDL_CDtrack popisuje jednotlivé stopy na CD, pro pochopení by měly stačit komentáře.
typedef struct
{
Uint8 id; // ID stopy
Uint8 type; // SDL_AUDIO_TRACK nebo SDL_DATA_TRACK
Uint16 unused;
Uint32 length; // Délka stopy ve framech
Uint32 offset; // Offset ve framech od začátku disku
} SDL_CDtrack;
SDL interně pracuje s framy, nicméně časové údaje lze velice jednoduše získat makrem FRAMES_TO_MSF(). Prvním argumentem je počet framů, který se má převést na čas, a do M, S, F budou uloženy minuty, sekundy a zbylý počet framů. Opačný směr je také možný – MSF_TO_FRAMES().
#define FRAMES_TO_MSF(f, M,S,F) \
{ \
int value = f; \
*(F) = value % CD_FPS; \
value /= CD_FPS; \
*(S) = value % 60; \
value /= 60; \
*(M) = value; \
}
#define MSF_TO_FRAMES(M, S, F) \
((M)*60*CD_FPS+(S)*CD_FPS+(F))
Pokud by byla potřeba pouze délka v sekundách, stačí jen obyčejné dělení frames / CD_FPS. V následujícím příkladě se vypíší informace o délce všech stop na CD.
int min, sec, fr;
SDL_CDStatus(g_cdrom);// Aktualizace informací
printf("Počet stop: %d\n", g_cdrom->numtracks);
for(int i = 0; i < g_cdrom->numtracks; i++)
{
FRAMES_TO_MSF(g_cdrom->track[i].length, &min, &sec, &fr);
printf("Stopa %d: %5d = %d:%2d, %2d\n", i,
g_cdrom->track[i].length, min, sec, fr);
}
Výstup bude u audio CD vypadat nějak takto.
Počet stop: 9
Stopa 0: 10087 = 2:14, 37
Stopa 1: 10568 = 2:20, 68
Stopa 2: 18475 = 4:06, 25
Stopa 3: 16778 = 3:43, 53
Stopa 4: 11059 = 2:27, 34
Stopa 5: 5423 = 1:12, 23
Stopa 6: 15167 = 3:22, 17
Stopa 7: 5851 = 1:18, 1
Stopa 8: 11906 = 2:38, 56
Přehrávání
Základní funkcí pro přehrávání je SDL_CDPlay(). Předává se jí počáteční frame a počet, který se má celkově přehrát. Pokud bude úspěšná vrátí nulu, jinak –1.
int SDL_CDPlay(SDL_CD *cdrom, int start, int length);
Mnohem častěji než SDL_CDPlay() se ale používá SDL_CDPlayTracks(), protože poskytuje snadnou volbu toho, co se má přehrávat.
int SDL_CDPlayTracks(SDL_CD *cdrom, int start_track,
int start_frame, int ntracks, int nframes);
Start_track a ntracks označují první přehrávanou stopu a jejich celkový počet. Start_frame je offsetem ve framech od počáteční stopy a nframes offsetem od poslední. Pokud budou poslední dva parametry nulové, přehrává se až do konce CD. Datové oblasti jsou automaticky přeskakovány. Následující tři příklady byly přebrány ze SDL dokumentace.
// Přehraje se celé CD
if(CD_INDRIVE(SDL_CDStatus(cdrom)))
SDL_CDPlayTracks(cdrom, 0, 0, 0, 0);
// Přehraje se poslední stopa
if(CD_INDRIVE(SDL_CDStatus(cdrom)))
SDL_CDPlayTracks(cdrom, cdrom->numtracks-1, 0, 0, 0);
// Přehraje 15 sekund ze druhé stopy
if(CD_INDRIVE(SDL_CDStatus(cdrom)))
SDL_CDPlayTracks(cdrom, 1, 0, 0, CD_FPS*15);
Následují nezbytné funkce každého přehrávání. Mimochodem, pokud se nezavolá SDL_CDStop(), CD se přehrává i po ukončení aplikace!
int SDL_CDPause(SDL_CD *cdrom); // Pozastavení
int SDL_CDResume(SDL_CD *cdrom);// Obnovení
int SDL_CDStop(SDL_CD *cdrom); // Zastavení
Pomocí SDL_CDEject() lze disk vysunout z mechaniky.
int SDL_CDEject(SDL_CD *cdrom);
Ukázkové programy
CD přehrávač
Program implementuje velice jednoduchý CD přehrávač, který umožňuje přechody mezi stopami, posuny při přehrávání, pozastavení a také vysunutí mechaniky. Po spuštění programu s volbou -h nebo –help se zobrazí ovládání. Všechny informace se vypisují do konzole. (Zdrojový kód se zvýrazněním syntaxe.)
Download
Pokračování
Zdárně jsme dokončili zvuky a hudbu, příště se budeme věnovat vícevláknovému programování.