Hallo zusammen!
Ich habe hier einen CD-Player für Linux-Systeme programmiert. Es war/ist ein Lernprogramm und hat
deswegen nur die nötigsten Funktionen.
Es wird gezeigt wie man unter Linux mit den CD-Rom Treiber interagieren kann.
Es gibt einfache Abspielfunktionen (Play, Pause, Resume, Stop) und noch ein paar kleine Extras.
Da es kein SDL oder Ähnliches benutzt, sollte es auf allen Linux-Systemen funktionieren, die einen C-Compiler installiert haben.
Es ist recht einfach eine Repeat-Funktion einzubauen oder auch Playlisten anzulegen, aber ich habe bewusst nur das Nötigste implementiert. Wer wirklich weiterentwickeln will, kann mir eine PM/E-Mail schicken!
Das UI ist trivial, aber naja.
PS.: Die Code-Formatierung ist mir hier nicht so gelungen!
Falls ihr mal mit Hardware-Programmierung anfangt, hilft euch das vielleicht etwas weiter.
Ich habe hier einen CD-Player für Linux-Systeme programmiert. Es war/ist ein Lernprogramm und hat
deswegen nur die nötigsten Funktionen.
Es wird gezeigt wie man unter Linux mit den CD-Rom Treiber interagieren kann.
Es gibt einfache Abspielfunktionen (Play, Pause, Resume, Stop) und noch ein paar kleine Extras.
Da es kein SDL oder Ähnliches benutzt, sollte es auf allen Linux-Systemen funktionieren, die einen C-Compiler installiert haben.
Es ist recht einfach eine Repeat-Funktion einzubauen oder auch Playlisten anzulegen, aber ich habe bewusst nur das Nötigste implementiert. Wer wirklich weiterentwickeln will, kann mir eine PM/E-Mail schicken!
Das UI ist trivial, aber naja.
Code:
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdlib.h>
#include <linux/cdrom.h>
#include <errno.h>
#define clr() printf("\x1B[2J")
int fd; /* global filedescriptor */
int print_help(void); /* prints the help screen on the display */
static int open_driver(char *); /* opens the cdrom driver for interaction */
static int open_tray(int); /* opens the cdrom tray */
static int close_tray(int); /* closes the cdrom tray */
static int stop_cdrom(int); /* stops the cdrom, should be done before closing fd */
static int capabilities(int); /* shows the capabilities of the selected (argv[1]) drive */
static int pause_cdrom(int); /* pauses the cd */
static int resume_cdrom(int); /* resume playing after the cd was paused */
static int print_content(int); /* prints some details about the cd content like frame positions, lenght etc. on the screen */
static play_cdrom(int, int); /* plays either the whole cd or just a single track, you decide */
static int print_status(int); /* prints the actual drive status on the screen */
int main(int, char**); /* main function, basicly to interact with the user */
int print_help(void)
{
clr();
printf("This is just a simple program, that shows how you can\n");
printf("interact with the cdrom driver on a Linux box\n\n");
printf("Usage: pac <device>\n");
printf("Example: pac /dev/cdrom\n\n");
getchar();getchar();
}
static int open_driver(char *device)
{
fd = open(device, O_RDONLY | O_NONBLOCK);
if(fd == -1)
{
if(errno == ENOMEDIUM) /* This does not work, but I don't know why */
printf("No cd in the drive\n");
else
perror("open_driver()");
exit(EXIT_FAILURE);
}
}
static int open_tray(int device)
{
if(ioctl(device, CDROMEJECT) == -1)
{
perror("open_tray()");
return EXIT_FAILURE;
}
}
static int close_tray(int device)
{
if(ioctl(device, CDROMCLOSETRAY) == -1)
{
perror("close_tray()");
return EXIT_FAILURE;
}
}
static int stop_cdrom(int device)
{
if(ioctl(device, CDROMSTOP) ==-1)
{
perror("stop_cdrom()");
return EXIT_FAILURE;
}
}
static int pause_cdrom(int device)
{
if(ioctl(device, CDROMPAUSE) == -1)
{
perror("pause_cdrom()");
return EXIT_FAILURE;
}
}
static int resume_cdrom(int device)
{
if(ioctl(device, CDROMRESUME) == -1)
{
perror("resume_cdrom()");
return EXIT_FAILURE;
}
}
static int capabilities(int device)
{
const char *answer[] = {"no", "yes"};
int caps = ioctl(device, CDROM_GET_CAPABILITY);
if(caps == -1)
{
perror("capabilities()");
return EXIT_FAILURE;
}
clr();
printf("drive capabilities:\n");
printf("\tcan close tray:\t\t\t\t%s\n", answer[!!(caps & CDC_CLOSE_TRAY)]);
printf("\tcan open tray:\t\t\t\t\%s\n", answer[!!(caps & CDC_OPEN_TRAY)]);
printf("\tcan lock tray:\t\t\t\t%s\n", answer[!!(caps & CDC_LOCK)]);
printf("\tprogrammable speed:\t\t\t%s\n", answer[!!(caps & CDC_SELECT_SPEED)]);
printf("\tdisc selection (jukebox):\t\t%s\n", answer[!!(caps & CDC_SELECT_DISC)]);
printf("\tcan read multi sessions:\t\t%s\n", answer[!!(caps & CDC_MULTI_SESSION)]);
printf("\tmedium catalog number (MCN):\t\t%s\n", answer[!!(caps & CDC_MCN)]);
printf("\tmedium changed:\t\t\t\t%s\n", answer[!!(caps & CDC_MEDIA_CHANGED)]);
printf("\taudio functions:\t\t\t%s\n", answer[!!(caps & CDC_PLAY_AUDIO)]);
printf("\thard reset device:\t\t\t%s\n", answer[!!(caps & CDC_RESET)]);
printf("\tdriver has non-standard ioctls:\t\t%s\n", answer[!!(caps & CDC_IOCTLS)]);
printf("\tdriver implements drive status:\t\t%s\n", answer[!!(caps & CDC_DRIVE_STATUS)]);
printf("\tdriver implements generic packtes:\t%s\n", answer[!!(caps & CDC_GENERIC_PACKET)]);
printf("\tdrive is a CD-R:\t\t\t%s\n", answer[!!(caps & CDC_CD_R)]);
printf("\tdrive is a CD-RW:\t\t\t%s\n", answer[!!(caps & CDC_CD_RW)]);
printf("\tdrive is a DVD:\t\t\t\t%s\n", answer[!!(caps & CDC_DVD)]);
printf("\tdrive is a DVD-R:\t\t\t%s\n", answer[!!(caps & CDC_DVD_R)]);
printf("\tdrive is a DVD-RAM:\t\t\t%s\n", answer[!!(caps & CDC_DVD_RAM)]);
printf("\tdrive is an MO device:\t\t\t%s\n", answer[!!(caps & CDC_MO_DRIVE)]);
printf("\tdrive can read MRW:\t\t\t%s\n", answer[!!(caps & CDC_MRW)]);
printf("\tdrive can write MRW:\t\t\t%s\n", answer[!!(caps & CDC_MRW_W)]);
printf("\tOK to open for WRITE:\t\t\t%s\n", answer[!!(caps & CDC_RAM)]);
getchar();getchar();
}
static int print_content(int device)
{
struct cdrom_tochdr tochdr;
struct cdrom_tocentry tocentry;
int track;
if(ioctl(device, CDROMREADTOCHDR, &tochdr) == -1)
{
perror("print_content()");
exit (EXIT_FAILURE);
}
clr();
printf("cd contains %i track(s):\n", tochdr.cdth_trk1);
for(track = tochdr.cdth_trk0; track <= tochdr.cdth_trk1; track++)
{
tocentry.cdte_track = track;
tocentry.cdte_format = CDROM_MSF;
if(ioctl(device, CDROMREADTOCENTRY, &tocentry) == -1)
{
perror("print_content()");
exit (EXIT_FAILURE);
}
printf("%3d: %02d:%02d:%02d (%06d) %s%s\n",
tocentry.cdte_track, tocentry.cdte_addr.msf.minute,
tocentry.cdte_addr.msf.second,
tocentry.cdte_addr.msf.frame,
tocentry.cdte_addr.msf.frame +
tocentry.cdte_addr.msf.second * 75 +
tocentry.cdte_addr.msf.minute * 75 * 60 - 150,
(tocentry.cdte_ctrl & CDROM_DATA_TRACK) ? "data" : "audio",
(track == CDROM_LEADOUT) ? " (leadout)" : ""); /*Does not work ??? */
}
getchar();getchar();
}
static int play_cdrom(int device, int song)
{
struct cdrom_tocentry tocentry;
struct cdrom_msf msf;
int track = song;
int lead = song;
if(song == 0)
{
track = 1;
lead = CDROM_LEADOUT;
}
else
{
track = song;
lead = song+1;
}
tocentry.cdte_track = track;
tocentry.cdte_format = CDROM_MSF;
if(ioctl(device, CDROMREADTOCENTRY, &tocentry) == -1)
{
perror("startrack(s) - play_cdrom()");
return EXIT_FAILURE;
}
msf.cdmsf_min0 = tocentry.cdte_addr.msf.minute;
msf.cdmsf_sec0 = tocentry.cdte_addr.msf.second;
msf.cdmsf_frame0 = tocentry.cdte_addr.msf.frame;
tocentry.cdte_track = lead;
tocentry.cdte_format = CDROM_MSF;
if(ioctl(device, CDROMREADTOCENTRY, &tocentry) == -1)
{
perror("lead track(s) - play_cdrom()");
return EXIT_FAILURE;
}
msf.cdmsf_min1 = tocentry.cdte_addr.msf.minute;
msf.cdmsf_sec1 = tocentry.cdte_addr.msf.second;
msf.cdmsf_frame1 = tocentry.cdte_addr.msf.frame;
if(ioctl(device, CDROMPLAYMSF, &msf) == -1)
{
perror("playing - play_cdrom()");
return EXIT_FAILURE;
}
}
static int print_status(int device)
{
struct cdrom_subchnl sub;
fflush(stdout);
sub.cdsc_format = CDROM_MSF;
if(ioctl(device, CDROMSUBCHNL, &sub) == -1)
{
perror("print_status()");
return EXIT_FAILURE;
}
clr();
printf("actual drive status: ");
switch (sub.cdsc_audiostatus)
{
case CDROM_AUDIO_INVALID: printf("invalid\n"); break;
case CDROM_AUDIO_PLAY: printf("playing"); break;
case CDROM_AUDIO_PAUSED: printf("paused"); break;
case CDROM_AUDIO_COMPLETED: printf("completed\n"); break;
case CDROM_AUDIO_ERROR: printf("error\n"); break;
case CDROM_AUDIO_NO_STATUS: printf("no status\n"); break;
default: printf("internal error: status unknown\n");
}
if(sub.cdsc_audiostatus == CDROM_AUDIO_PLAY || sub.cdsc_audiostatus == CDROM_AUDIO_PAUSED)
{
printf(" at: %02d:%02d (absolute) / %02d:%02d (relative) - track %d\n",
sub.cdsc_absaddr.msf.minute,
sub.cdsc_absaddr.msf.second,
sub.cdsc_reladdr.msf.minute,
sub.cdsc_reladdr.msf.second,
sub.cdsc_trk);
}
getchar();getchar();
}
int main(int argc, char **argv)
{
int track, input;
if(argc < 2)
{
print_help();
return EXIT_FAILURE;
}
open_driver(argv[1]);
do{
clr();
printf(" -1- open cd tray\n");
printf(" -2- close cd tray\n");
printf(" -3- show drive capabilities\n");
printf(" -4- play the whole cd\n");
printf(" -5- play a single track\n");
printf(" -6- pause the cd\n");
printf(" -7- resume playing\n");
printf(" -8- stop the cd\n");
printf(" -9- show cd status\n");
printf("-10- show cd content\n");
printf("-11- show help dialog\n");
printf("-12- quit the program\n");
printf("your selection: ");
scanf("%d", &input);
switch(input)
{
case 1: open_tray(fd); break;
case 2: close_tray(fd); break;
case 3: capabilities(fd); break;
case 4: play_cdrom(fd, 0); break;
case 5: printf("enter track to play: ");
scanf("%i", &track);
play_cdrom(fd, track); break;
case 6: pause_cdrom(fd); break;
case 7: resume_cdrom(fd); break;
case 8: stop_cdrom(fd); break;
case 9: print_status(fd); break;
case 10: print_content(fd); break;
case 11: print_help(); break;
case 12: printf("thanks for using;)\n"); break;
default: printf("not a valid option\n");
}
}while(input != 12);
close(fd);
return EXIT_SUCCESS;
}
PS.: Die Code-Formatierung ist mir hier nicht so gelungen!
Falls ihr mal mit Hardware-Programmierung anfangt, hilft euch das vielleicht etwas weiter.