Ušetřete

Hlavní navigace

SDL: Hry nejen pro Linux (21)

Další oblastí knihovny SDL, kterou si popíšeme, bude API pro práci s CD-ROM. Po přečtení tohoto článku byste měli být schopni si vytvořit jednoduchý CD přehrávač, který zahrnuje přehrávání a pauzy, listování a pohyb ve skladbách a také vysouvání mechaniky pro vložení nového disku.

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í.

Michal Turek

Autor studuje první ročník FEL ČVUT Praha, baví ho vše kolem počítačů, zvláště programování v jazycích PHP a C/C++ včetně počítačové grafiky pod knihovnou OpenGL.

Ohodnoťte jako ve škole:
Průměrná známka 2,87

Školení Google Analytics

  •  
    Jak vyhodnocovat úspěšnost reklamních kampaní.
  • Jak ovládat Google Analytics a najít v něm to, co potřebuji.
  • Co je to konverze a jak měřit hodnotu objednávek z webu.

Detailní informace o školení Google Analytics »

       
1 názor Vstoupit do diskuse
poslední názor přidán 12. 7. 2006 16:29

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem