/*************************************************************************** * Copyright (C) 2005 by Michal Turek - Woq * * WOQ (zavinac) seznam.cz * * * * Program implementuje velice jednoduchy CD prehravac, ktery umoznuje * * prechody mezi stopami, posuny pri prehravani, pozastaveni a vysunuti * * mechaniky. Po spusteni programu s volbou -h nebo --help se zobrazi * * ovladani. Vsechny informace se vypisuji do konzole. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include <stdio.h> #include <string.h> #include <SDL.h> /* * Symbolicke konstanty */ #define SDL_SUBSYSTEMS SDL_INIT_VIDEO|SDL_INIT_CDROM #define WIN_WIDTH 320 #define WIN_HEIGHT 240 #define WIN_BPP 0 #define WIN_TITLE "Simple CD Player" // O kolik sekund se posouva prehravani #define TIME 5 /* * Funkcni prototypy */ void DrivesInfo(); // Informace o mechanikach void TrackInfo(SDL_CD *cdrom, int track = -1); // Informace o stopach na CD void InsertCD(SDL_CD *cdrom); // Ceka na vlozeni CD bool Init(); // Inicializace void Destroy(); // Deinicializace bool ProcessEvent(); // Osetruje udalosti int main(int argc, char *argv[]); // Vstup do programu /* * Globalni promenne */ Uint8 g_win_flags = SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE; SDL_Surface *g_screen; // Surface okna SDL_CD *g_cdrom = NULL; // Indetifikator CD mechaniky /* * Vypise pocet CD mechanik v systemu a jejich jmena */ void DrivesInfo() { putchar('\n'); int num_drives = SDL_CDNumDrives(); printf("Drives available: %d\n", num_drives); for(int i = 0; i < num_drives; i++) printf("\tDrive %d: %s\n", i, SDL_CDName(i)); } /* * Vypise informace o stope, pokud track == -1, o vsech */ void TrackInfo(SDL_CD *cdrom, int track) { int m, s, f; char* trtype; SDL_CDStatus(cdrom); if(track == -1)// Vsechny stopy { printf("\nDrive tracks: %d\n", cdrom->numtracks); for(int i = 0; i < cdrom->numtracks; i++) { FRAMES_TO_MSF(cdrom->track[i].length, &m, &s, &f); if(f > 0) s++; switch(cdrom->track[i].type) { case SDL_AUDIO_TRACK: trtype="audio"; break; case SDL_DATA_TRACK: trtype="data"; break; default: trtype="unknown"; break; } printf("\tTrack %d: %d:%2.2d / %d\t[%s track]\n", cdrom->track[i].id, m, s, cdrom->track[i].length, trtype); } putchar('\n'); } else// Pouze dana stopa { if(track >= 0 && track < g_cdrom->numtracks) { FRAMES_TO_MSF(cdrom->track[track].length, &m, &s, &f); if(f > 0) s++; switch(cdrom->track[track].type) { case SDL_AUDIO_TRACK: trtype="audio"; break; case SDL_DATA_TRACK: trtype="data"; break; default: trtype="unknown"; break; } printf("Track %d: %d:%2.2d / %d\t[%s track]\n", cdrom->track[track].id, m, s, cdrom->track[track].length, trtype); } else { fprintf(stderr, "Track %d is not valid.\n", track); } } } /* * Otevre mechaniku a ceka na vlozeni CD */ void InsertCD(SDL_CD *cdrom) { SDL_CDStop(cdrom); SDL_CDEject(cdrom); // Ceka na vlozeni CD, testy kazde pul sekundy while(!CD_INDRIVE(SDL_CDStatus(cdrom))) { SDL_Delay(500); // ESC bude stale dostupny... SDL_PumpEvents(); if(SDL_GetKeyState(NULL)[SDLK_ESCAPE] == SDL_PRESSED) return; } TrackInfo(cdrom); SDL_CDPlayTracks(cdrom, 0, 0, 0, 0); } /* * Inicializacni funkce */ bool Init() { // Inicializace SDL if(SDL_Init(SDL_SUBSYSTEMS) == -1) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return false; } // Nastaveni ikony SDL_Surface *icon = SDL_LoadBMP("./icon.bmp"); if(icon != NULL) { SDL_WM_SetIcon(icon, NULL); SDL_FreeSurface(icon); } // Vytvori okno s definovanymi vlastnostmi g_screen = SDL_SetVideoMode(WIN_WIDTH, WIN_HEIGHT, WIN_BPP, g_win_flags); if(g_screen == NULL) { fprintf(stderr, "Unable to set %dx%d video: %s\n", WIN_WIDTH, WIN_HEIGHT, SDL_GetError()); return false; } // Titulek okna SDL_WM_SetCaption(WIN_TITLE, NULL); // CD-ROM if(SDL_CDNumDrives() < 0) { fprintf(stderr, "There is no available CD-ROM drive\n"); return false; } // Informace o mechanikach v systemu DrivesInfo(); // Otevre prvni if((g_cdrom = SDL_CDOpen(0)) == NULL) { fprintf(stderr, "Unable to open CD-ROM: %s\n", SDL_GetError()); return false; } // Prehraje cele CD if(CD_INDRIVE(SDL_CDStatus(g_cdrom))) { TrackInfo(g_cdrom); SDL_CDPlayTracks(g_cdrom, 0, 0, 0, 0); } else { printf("There is no disk in drive. Waiting...\n"); InsertCD(g_cdrom); } return true; } /* * Deinicializacni funkce */ void Destroy() { if(g_cdrom != NULL) { // Zastavi prehravani if(SDL_CDStatus(g_cdrom) == CD_PLAYING) SDL_CDStop(g_cdrom); // Uvolni strukturu SDL_CDClose(g_cdrom); g_cdrom = NULL; } SDL_Quit(); } /* * Osetreni udalosti */ bool ProcessEvent() { SDL_Event event; while(SDL_WaitEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: switch(event.key.keysym.sym) { // Skok na predchazejici stopu case SDLK_UP: if(!CD_INDRIVE(SDL_CDStatus(g_cdrom)) || g_cdrom->cur_track <= 0) { break; } TrackInfo(g_cdrom, g_cdrom->cur_track-1); SDL_CDPlayTracks(g_cdrom, g_cdrom->cur_track-1, 0, 0, 0); break; // Skok na nasledujici stopu case SDLK_DOWN: if(!CD_INDRIVE(SDL_CDStatus(g_cdrom)) || g_cdrom->cur_track > g_cdrom->numtracks-2) { break; } TrackInfo(g_cdrom, g_cdrom->cur_track+1); SDL_CDPlayTracks(g_cdrom, g_cdrom->cur_track+1, 0, 0, 0); break; // Posun ve stope doleva case SDLK_LEFT: { if(SDL_CDStatus(g_cdrom) != CD_PLAYING) break; int frame = g_cdrom->cur_frame - TIME * CD_FPS; if(frame > 0) { SDL_CDPlayTracks(g_cdrom, g_cdrom->cur_track, frame, 0, 0); } } break; // Posun ve stope doprava case SDLK_RIGHT: { if(SDL_CDStatus(g_cdrom) != CD_PLAYING) break; int frame = g_cdrom->cur_frame + TIME * CD_FPS; if(frame < (int)g_cdrom->track[g_cdrom->cur_track].length) { SDL_CDPlayTracks(g_cdrom, g_cdrom->cur_track, frame, 0, 0); } } break; // Vymena CD case SDLK_BACKSPACE: InsertCD(g_cdrom); break; // Informace o stope case SDLK_RETURN: if(SDL_CDStatus(g_cdrom) == CD_PLAYING) TrackInfo(g_cdrom, g_cdrom->cur_track); break; // Pozastaveni case SDLK_SPACE: if(SDL_CDStatus(g_cdrom) == CD_PLAYING) SDL_CDPause(g_cdrom); else SDL_CDResume(g_cdrom); break; case SDLK_ESCAPE: return false; break; default: break; } break; case SDL_QUIT: return false; break; default: break; } } return true; } /* * Vstup do programu */ int main(int argc, char *argv[]) { printf(WIN_TITLE); if(argc > 1) { if(strcmp(argv[1], "-h") || strcmp(argv[1], "--help")) { putchar('\n'); printf("Usage:\t%s [-h]\n\t%s [--help]\n", argv[0], argv[0]); printf("Keyboard:\n"); printf("\t[ESC]\t\texit\n"); printf("\t[DOWN]\t\tprevious track\n"); printf("\t[UP]\t\tnext track\n"); printf("\t[LEFT]\t\tmove %d seconds left\n", TIME); printf("\t[RIGHT]\t\tmove %d seconds right\n", TIME); printf("\t[ENTER]\t\tinfo about track\n"); printf("\t[SPACE]\t\tpause/resume\n"); printf("\t[BACKSPACE]\tnew CD\n"); return 0; } } printf("\nPress ESC key to quit.\n"); // Inicializace if(!Init()) { Destroy(); return 1; } // Hlavni smycka programu bool done = false; while(!done) { done = !ProcessEvent(); } // Deinicializace a konec Destroy(); return 0; }