[PATCH] vcd support ported from main (and as such removing globals)

Fabian Franz <[email protected]>
Newsgroups gmane.comp.video.mplayer.g2.devel
Message-ID <[email protected]>
Hi,

attached patch is based on vcd from main and has infrastructure from g2.

There are some comments with //FF: - Those are just for things I wasn't sure 
with and should be removed before applying.

Hope it did that job (with removing the global vars).

cu

Fabian

_______________________________________________
MPlayer-G2-dev mailing list
[email protected]
http://mplayerhq.hu/mailman/listinfo/mplayer-g2-dev
g2-vcd-port.diff (text/x-diff, 20.6 KB)
diff -Nur g2-orig/stream/stream_vcd.c g2/stream/stream_vcd.c
--- g2-orig/stream/stream_vcd.c	2003-03-31 02:38:52.000000000 +0200
+++ g2/stream/stream_vcd.c	2003-05-23 04:23:40.000000000 +0200
@@ -2,30 +2,18 @@
 #include "../config.h"
 
 #ifdef HAVE_VCD
+#include "../mp_msg.h"
+#include "stream.h"
+#include "../help_mp.h"
 
-#include <stdio.h>
+#include <fcntl.h>
 #include <stdlib.h>
-#include <string.h>
 #include <unistd.h>
-#include <fcntl.h>
-
-//#include <sys/types.h>
-#include <sys/stat.h>
 #include <sys/ioctl.h>
-//#include <sys/wait.h>
-//#include <signal.h>
+#include <errno.h>
 
 #ifdef __FreeBSD__
 #include <sys/cdrio.h>
-#endif
-
-
-#include "../mp_msg.h"
-#include "../help_mp.h"
-
-#include "stream.h"
-
-#ifdef __FreeBSD__
 #include "vcd_read_fbsd.h" 
 #elif defined(__NetBSD__)
 #include "vcd_read_nbsd.h" 
@@ -33,55 +21,113 @@
 #include "vcd_read.h"
 #endif
 
-//struct stream_priv_s {
-//  struct cdrom_tocentry vcd_entry;
-//};
+static struct stream_priv_s {
+  int track;
+  char* device;
+} stream_priv_dflts = {
+  1,
+  DEFAULT_CDROM_DEVICE
+};
+
+#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
+/// URL definition
+/*static m_option_t stream_opts_fields[] = {
+  { "track", ST_OFF(track), CONF_TYPE_INT, M_OPT_MIN, 1, 0, NULL },
+  { "device", ST_OFF(device), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  /// For url parsing
+  { "hostname", ST_OFF(track), CONF_TYPE_INT, M_OPT_MIN, 1, 0, NULL },
+  { "filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+static struct m_struct_st stream_opts = {
+  "vcd",
+  sizeof(struct stream_priv_s),
+  &stream_priv_dflts,
+  stream_opts_fields
+};*/
 
-static int driver_open(stream_t *s){
+//static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
+static int driver_open(stream_t *stream) {
   int vcd_track;
   int vcd_last_track;
-  int ret,ret2;
-  int f;
-  url_parse_range(s->url, &vcd_track, &vcd_last_track, &cdrom_device);
+  int ret,ret2,f;
+  mp_vcd_priv_t* vcd;
+#ifdef __FreeBSD__
+  int bsize = VCD_SECTOR_SIZE;
+#endif
+  url_parse_range(stream->url, &vcd_track, &vcd_last_track, &cdrom_device);
   if(!vcd_track) vcd_track=1;
-  s->fd=f=open(cdrom_device,O_RDONLY);
-  if(f<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CdDevNotfound,cdrom_device);return 0; }
-  vcd_read_toc(f);
-  ret2=vcd_get_track_end(f,vcd_last_track ? vcd_last_track : vcd_track);
-  if(ret2<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (get)\n");return 0;}
-  ret=vcd_seek_to_track(f,vcd_track);
-  if(ret<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (seek)\n");return 0;}
+
+  f=open(cdrom_device,O_RDONLY);
+  if(f<0){ 
+    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CdDevNotfound,cdrom_device);
+    close(f);
+    return 0;
+  }
+
+  vcd = vcd_read_toc(f);
+  if(!vcd) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,"Failed to get cd toc\n"); //FIXME: Needs to be internationalized
+    close(f);
+    return 0;
+  }
+  ret2=vcd_get_track_end(vcd,vcd_last_track ? vcd_last_track : vcd_track); // FF: So Right ?
+  if(ret2<0){
+    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (get)\n");
+    close(f);
+    free(vcd);
+    return 0;
+  }
+  ret=vcd_seek_to_track(vcd,vcd_track);
+  if(ret<0){
+    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (seek)\n");
+    close(f);
+    free(vcd);
+    return 0;
+  }
   mp_msg(MSGT_OPEN,MSGL_V,"VCD start byte position: 0x%X  end: 0x%X\n",ret,ret2);
+
 #ifdef __FreeBSD__
   if (ioctl (f, CDRIOCSETBLOCKSIZE, &bsize) == -1) {
-        perror ( "Error in CDRIOCSETBLOCKSIZE");
+    mp_msg(MSGT_OPEN,MSGL_WARN,"Error in CDRIOCSETBLOCKSIZE");
   }
 #endif
-  s->start_pos=ret;
-  s->end_pos=ret2;
-  s->buf_size=VCD_SECTOR_DATA;
+
+  stream->fd = f;
+  //stream->type = STREAMTYPE_VCD; // FF: Assuming that it is already correctly set by stream-master
+  stream->buf_size = VCD_SECTOR_DATA;
+  stream->start_pos=ret;
+  stream->end_pos=ret2;
+  stream->priv = (struct stream_priv_s*)vcd;
+
   return 1;
 }
 
 static int driver_fill(stream_t *s){
-  return vcd_read(s->fd,s->buffer);
+  return vcd_read((mp_vcd_priv_t*)s->priv,s->buffer);
 }
 
-static int driver_seek(stream_t *s,off_t pos){
+static int driver_seek(stream_t *s,off_t pos) {
   s->pos=(pos/VCD_SECTOR_DATA)*VCD_SECTOR_DATA;
-  vcd_set_msf(s->pos/VCD_SECTOR_DATA);
+  vcd_set_msf((mp_vcd_priv_t*)s->priv,s->pos/VCD_SECTOR_DATA);
+  return 1;
+}
+
+static int driver_free(stream_t *stream) {
+  if (stream->priv)
+    free(stream->priv);
   return 1;
 }
 
 stream_driver_t stream_driver_vcd = {
     "vcd",
     "VideoCD/SVCD/XCD driver",
-    "A'rpi",
+    "Albeu & A'rpi (ported by Fabian Franz)",
     driver_open,
     NULL, //reset,
     driver_fill,
     driver_seek,
-    NULL //free
+    driver_free
 };
 
 #endif
diff -Nur g2-orig/stream/vcd_read_fbsd.h g2/stream/vcd_read_fbsd.h
--- g2-orig/stream/vcd_read_fbsd.h	1970-01-01 01:00:00.000000000 +0100
+++ g2/stream/vcd_read_fbsd.h	2003-05-23 03:58:22.000000000 +0200
@@ -0,0 +1,111 @@
+#include <sys/cdio.h>
+#include <sys/cdrio.h>
+
+//=================== VideoCD ==========================
+#define	CDROM_LEADOUT	0xAA
+
+typedef struct {
+	uint8_t sync            [12];
+	uint8_t header          [4];
+	uint8_t subheader       [8];
+	uint8_t data            [2324];
+	uint8_t spare           [4];
+} cdsector_t;
+
+typedef struct mp_vcd_priv_st {
+  int fd;
+  struct ioc_read_toc_single_entry entry;
+  cdsector_t buf;
+} mp_vcd_priv_t;
+
+static inline void vcd_set_msf(mp_vcd_priv_t* vcd, unsigned int sect){
+  vcd->entry.entry.addr.msf.frame=sect%75;
+  sect=sect/75;
+  vcd->entry.entry.addr.msf.second=sect%60;
+  sect=sect/60;
+  vcd->entry.entry.addr.msf.minute=sect;
+}
+
+static inline unsigned int vcd_get_msf(mp_vcd_priv_t* vcd){
+  return vcd->entry.entry.addr.msf.frame +
+        (vcd->entry.entry.addr.msf.second+
+         vcd->entry.entry.addr.msf.minute*60)*75;
+}
+
+int vcd_seek_to_track(mp_vcd_priv_t* vcd, int track){
+  vcd->entry.address_format = CD_MSF_FORMAT;
+  vcd->entry.track  = track;
+  if (ioctl(vcd->fd, CDIOREADTOCENTRY, &vcd->entry)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif1: %s\n",strerror(errno));
+    return -1;
+  }
+  return VCD_SECTOR_DATA*vcd_get_msf(vcd);
+}
+
+int vcd_get_track_end(mp_vcd_priv_t* vcd, int track){
+  struct ioc_toc_header tochdr;
+  if (ioctl(vcd->fd,CDIOREADTOCHEADER,&tochdr)==-1) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+    return -1;
+  }
+  vcd->entry.address_format = CD_MSF_FORMAT;
+  vcd->entry.track  = track<tochdr.ending_track?(track+1):CDROM_LEADOUT;
+  if (ioctl(vcd->fd, CDIOREADTOCENTRY, &vcd->entry)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif2: %s\n",strerror(errno));
+    return -1;
+  }
+  return VCD_SECTOR_DATA*vcd_get_msf(vcd);
+}
+
+mp_vcd_priv_t* vcd_read_toc(int fd){
+  struct ioc_toc_header tochdr;
+  mp_vcd_priv_t* vcd;
+  int i;
+  if (ioctl(fd,CDIOREADTOCHEADER,&tochdr)==-1) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+    return NULL;
+  }
+  for (i=tochdr.starting_track ; i<=tochdr.ending_track ; i++){
+      struct ioc_read_toc_single_entry tocentry;
+
+      tocentry.track  = i;
+      tocentry.address_format = CD_MSF_FORMAT;
+
+      if (ioctl(fd,CDIOREADTOCENTRY,&tocentry)==-1) {
+	mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc entry: %s\n",strerror(errno));
+	return NULL;
+      }
+        
+      mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d:  adr=%d  ctrl=%d  format=%d  %02d:%02d:%02d\n",
+          (int)tocentry.track,
+          (int)tocentry.entry.addr_type,
+          (int)tocentry.entry.control,
+          (int)tocentry.address_format,
+          (int)tocentry.entry.addr.msf.minute,
+          (int)tocentry.entry.addr.msf.second,
+          (int)tocentry.entry.addr.msf.frame
+      );
+    }
+  vcd = malloc(sizeof(mp_vcd_priv_t));
+  vcd->fd = fd;
+  return vcd;  
+}
+
+static int vcd_read(mp_vcd_priv_t* vcd,char *mem){
+
+      if (pread(vcd->fd,&vcd->buf,VCD_SECTOR_SIZE,vcd_get_msf(vcd)*VCD_SECTOR_SIZE)
+	 != VCD_SECTOR_SIZE) return 0;  // EOF?
+
+      vcd->entry.entry.addr.msf.frame++;
+      if (vcd->entry.entry.addr.msf.frame==75){
+        vcd->entry.entry.addr.msf.frame=0;
+        vcd->entry.entry.addr.msf.second++;
+        if (vcd->entry.entry.addr.msf.second==60){
+          vcd->entry.entry.addr.msf.second=0;
+          vcd->entry.entry.addr.msf.minute++;
+        }
+      }
+      memcpy(mem,vcd->buf.data,VCD_SECTOR_DATA);
+      return VCD_SECTOR_DATA;
+}
+
diff -Nur g2-orig/stream/vcd_read.h g2/stream/vcd_read.h
--- g2-orig/stream/vcd_read.h	2002-09-15 20:48:16.000000000 +0200
+++ g2/stream/vcd_read.h	2003-05-23 03:58:22.000000000 +0200
@@ -1,68 +1,80 @@
 //=================== VideoCD ==========================
 #if	defined(linux) || defined(sun) || defined(__bsdi__)
 
+typedef struct mp_vcd_priv_st mp_vcd_priv_t;
+
 #if	defined(linux)
 #include <linux/cdrom.h>
 #elif	defined(sun)
 #include <sys/cdio.h>
-static int sun_vcd_read(int, int*);
+static int sun_vcd_read(mp_vcd_priv_t*, int*);
 #elif	defined(__bsdi__)
 #include <dvd.h>
 #endif
 
+struct mp_vcd_priv_st {
+  int fd;
+  struct cdrom_tocentry entry;
+  char buf[VCD_SECTOR_SIZE];
+};
 
-static struct cdrom_tocentry vcd_entry;
-
-static inline void vcd_set_msf(unsigned int sect){
-  vcd_entry.cdte_addr.msf.frame=sect%75;
+static inline void vcd_set_msf(mp_vcd_priv_t* vcd, unsigned int sect){
+  vcd->entry.cdte_addr.msf.frame=sect%75;
   sect=sect/75;
-  vcd_entry.cdte_addr.msf.second=sect%60;
+  vcd->entry.cdte_addr.msf.second=sect%60;
   sect=sect/60;
-  vcd_entry.cdte_addr.msf.minute=sect;
+  vcd->entry.cdte_addr.msf.minute=sect;
 }
 
-static inline unsigned int vcd_get_msf(){
-  return vcd_entry.cdte_addr.msf.frame +
-        (vcd_entry.cdte_addr.msf.second+
-         vcd_entry.cdte_addr.msf.minute*60)*75;
+static inline unsigned int vcd_get_msf(mp_vcd_priv_t* vcd){
+  return vcd->entry.cdte_addr.msf.frame +
+        (vcd->entry.cdte_addr.msf.second+
+         vcd->entry.cdte_addr.msf.minute*60)*75;
 }
 
-int vcd_seek_to_track(int fd,int track){
-  vcd_entry.cdte_format = CDROM_MSF;
-  vcd_entry.cdte_track  = track;
-  if (ioctl(fd, CDROMREADTOCENTRY, &vcd_entry)) {
-    perror("ioctl dif1");
+int vcd_seek_to_track(mp_vcd_priv_t* vcd,int track){
+  vcd->entry.cdte_format = CDROM_MSF;
+  vcd->entry.cdte_track  = track;
+  if (ioctl(vcd->fd, CDROMREADTOCENTRY, &vcd->entry)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif1: %s\n",strerror(errno));
     return -1;
   }
-  return VCD_SECTOR_DATA*vcd_get_msf();
+  return VCD_SECTOR_DATA*vcd_get_msf(vcd);
 }
 
-int vcd_get_track_end(int fd,int track){
+int vcd_get_track_end(mp_vcd_priv_t* vcd,int track){
   struct cdrom_tochdr tochdr;
-  if (ioctl(fd,CDROMREADTOCHDR,&tochdr)==-1)
-    { perror("read CDROM toc header: "); return -1; }
-  vcd_entry.cdte_format = CDROM_MSF;
-  vcd_entry.cdte_track  = track<tochdr.cdth_trk1?(track+1):CDROM_LEADOUT;
-  if (ioctl(fd, CDROMREADTOCENTRY, &vcd_entry)) {
-    perror("ioctl dif2");
+  if (ioctl(vcd->fd,CDROMREADTOCHDR,&tochdr)==-1) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+    return -1;
+  }
+  vcd->entry.cdte_format = CDROM_MSF;
+  vcd->entry.cdte_track  = track<tochdr.cdth_trk1?(track+1):CDROM_LEADOUT;
+  if (ioctl(vcd->fd, CDROMREADTOCENTRY, &vcd->entry)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif2: %s\n",strerror(errno));
     return -1;
   }
-  return VCD_SECTOR_DATA*vcd_get_msf();
+  return VCD_SECTOR_DATA*vcd_get_msf(vcd);
 }
 
-void vcd_read_toc(int fd){
+mp_vcd_priv_t* vcd_read_toc(int fd){
   struct cdrom_tochdr tochdr;
+  mp_vcd_priv_t* vcd;
   int i;
-  if (ioctl(fd,CDROMREADTOCHDR,&tochdr)==-1)
-    { perror("read CDROM toc header: "); return; }
+  if (ioctl(fd,CDROMREADTOCHDR,&tochdr)==-1) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+    return NULL;
+  }
   for (i=tochdr.cdth_trk0 ; i<=tochdr.cdth_trk1 ; i++){
       struct cdrom_tocentry tocentry;
 
       tocentry.cdte_track  = i;
       tocentry.cdte_format = CDROM_MSF;
 
-      if (ioctl(fd,CDROMREADTOCENTRY,&tocentry)==-1)
-	{ perror("read CDROM toc entry: "); return; }
+      if (ioctl(fd,CDROMREADTOCENTRY,&tocentry)==-1) {
+	mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc entry: %s\n",strerror(errno));
+	return NULL;
+      }
         
       mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d:  adr=%d  ctrl=%d  format=%d  %02d:%02d:%02d  mode: %d\n",
           (int)tocentry.cdte_track,
@@ -75,31 +87,31 @@
           (int)tocentry.cdte_datamode
       );
     }
+  vcd = malloc(sizeof(mp_vcd_priv_t));
+  vcd->fd = fd;
+  return vcd;
 }
 
-
-static char vcd_buf[VCD_SECTOR_SIZE];
-
-static int vcd_read(int fd,char *mem){
+static int vcd_read(mp_vcd_priv_t* vcd,char *mem){
 #if	defined(linux) || defined(__bsdi__)
-  memcpy(vcd_buf,&vcd_entry.cdte_addr.msf,sizeof(struct cdrom_msf));
-  if(ioctl(fd,CDROMREADRAW,vcd_buf)==-1) return 0; // EOF?
-  memcpy(mem,&vcd_buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA);
+  memcpy(vcd->buf,&vcd->entry.cdte_addr.msf,sizeof(struct cdrom_msf));
+  if(ioctl(vcd->fd,CDROMREADRAW,vcd->buf)==-1) return 0; // EOF?
+  memcpy(mem,&vcd->buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA);
 #elif	defined(sun)
   {
     int offset;
-    if (sun_vcd_read(fd, &offset) <= 0) return 0;
-    memcpy(mem,&vcd_buf[offset],VCD_SECTOR_DATA);
+    if (sun_vcd_read(vcd->fd, &offset) <= 0) return 0;
+    memcpy(mem,&vcd->buf[offset],VCD_SECTOR_DATA);
   }
 #endif
 
-  vcd_entry.cdte_addr.msf.frame++;
-  if (vcd_entry.cdte_addr.msf.frame==75){
-    vcd_entry.cdte_addr.msf.frame=0;
-    vcd_entry.cdte_addr.msf.second++;
-    if (vcd_entry.cdte_addr.msf.second==60){
-      vcd_entry.cdte_addr.msf.second=0;
-      vcd_entry.cdte_addr.msf.minute++;
+  vcd->entry.cdte_addr.msf.frame++;
+  if (vcd->entry.cdte_addr.msf.frame==75){
+    vcd->entry.cdte_addr.msf.frame=0;
+    vcd->entry.cdte_addr.msf.second++;
+    if (vcd->entry.cdte_addr.msf.second==60){
+      vcd->entry.cdte_addr.msf.second=0;
+      vcd->entry.cdte_addr.msf.minute++;
     }
   }
     
@@ -116,35 +128,35 @@
 #define	SUN_SCSIREAD	3
 #define	SUN_VCDREAD	SUN_SCSIREAD
 
-static int sun_vcd_read(int fd, int *offset)
+static int sun_vcd_read(mp_vcd_priv_t* vcd, int *offset)
 {
 #if SUN_VCDREAD == SUN_XAREAD
   struct cdrom_cdxa cdxa;
-  cdxa.cdxa_addr = vcd_get_msf();
+  cdxa.cdxa_addr = vcd_get_msf(vcd);
   cdxa.cdxa_length = 1;
-  cdxa.cdxa_data = vcd_buf;
+  cdxa.cdxa_data = vcd->buf;
   cdxa.cdxa_format = CDROM_XA_SECTOR_DATA;
   
   if(ioctl(fd,CDROMCDXA,&cdxa)==-1) {
-    perror("CDROMCDXA");
+    mp_msg(MSGT_STREAM,MSGL_ERR,"CDROMCDXA: %s\n",strerror(errno));
     return 0;
   }
   *offset = 0;
 #elif SUN_VCDREAD == SUN_MODE2READ
   struct cdrom_read cdread;
-  cdread.cdread_lba = 4*vcd_get_msf();
-  cdread.cdread_bufaddr = vcd_buf;
+  cdread.cdread_lba = 4*vcd_get_msf(vcd);
+  cdread.cdread_bufaddr = vcd->buf;
   cdread.cdread_buflen = 2336;
 
   if(ioctl(fd,CDROMREADMODE2,&cdread)==-1) {
-    perror("CDROMREADMODE2");
+    mp_msg(MSGT_STREAM,MSGL_ERR,"CDROMREADMODE2: %s\n",strerror(errno));
     return 0;
   }
   *offset = 8;
 #elif SUN_VCDREAD == SUN_SCSIREAD
   struct uscsi_cmd sc;
   union scsi_cdb cdb;
-  int lba = vcd_get_msf();
+  int lba = vcd_get_msf(vcd);
   int blocks = 1;
   int sector_type;
   int sync, header_code, user_data, edc_ecc, error_field;
@@ -179,16 +191,16 @@
 
   sc.uscsi_cdb = (caddr_t)&cdb;
   sc.uscsi_cdblen = 12;
-  sc.uscsi_bufaddr = vcd_buf;
+  sc.uscsi_bufaddr = vcd->buf;
   sc.uscsi_buflen = 2336;
   sc.uscsi_flags = USCSI_ISOLATE | USCSI_READ;
   sc.uscsi_timeout = 20;
   if (ioctl(fd, USCSICMD, &sc)) {
-      perror("USCSICMD: READ CD");
+      mp_msg(MSGT_STREAM,MSGL_ERR,"USCSICMD: READ CD: %s\n",strerror(errno));
       return -1;
   }
   if (sc.uscsi_status) {
-      fprintf(stderr, "scsi command failed with status %d\n", sc.uscsi_status);
+      mp_msg(MSGT_STREAM,MSGL_ERR,"scsi command failed with status %d\n", sc.uscsi_status);
       return -1;
   }
   *offset = 0;
diff -Nur g2-orig/stream/vcd_read_nbsd.h g2/stream/vcd_read_nbsd.h
--- g2-orig/stream/vcd_read_nbsd.h	1970-01-01 01:00:00.000000000 +0100
+++ g2/stream/vcd_read_nbsd.h	2003-05-23 03:58:22.000000000 +0200
@@ -0,0 +1,170 @@
+
+#include <sys/types.h>
+#include <sys/inttypes.h>
+#include <sys/cdio.h>
+#include <sys/scsiio.h>
+
+#define	CDROM_LEADOUT	0xAA
+
+typedef struct mp_vcd_priv_st {
+  int fd;
+  struct ioc_read_toc_entry entry;
+  struct cd_toc_entry entry_data;
+} mp_vcd_priv_t;
+
+static inline void 
+vcd_set_msf(mp_vcd_priv_t* vcd, unsigned int sect)
+{
+  vcd->entry_data.addr.msf.frame = sect % 75;
+  sect = sect / 75;
+  vcd->entry_data.addr.msf.second = sect % 60;
+  sect = sect / 60;
+  vcd->entry_data.addr.msf.minute = sect;
+}
+
+static inline void
+vcd_inc_msf(mp_vcd_priv_t* vcd)
+{
+  vcd->entry_data.addr.msf.frame++;
+  if (vcd->entry_data.addr.msf.frame==75){
+    vcd->entry_data.addr.msf.frame=0;
+    vcd->entry_data.addr.msf.second++;
+    if (vcd->entry_data.addr.msf.second==60){
+      vcd->entry_data.addr.msf.second=0;
+      vcd->entry_data.addr.msf.minute++;
+    }
+  }
+}
+
+static inline unsigned int 
+vcd_get_msf(mp_vcd_priv_t* vcd)
+{
+  return vcd->entry_data.addr.msf.frame +
+  (vcd->entry_data.addr.msf.second +
+   vcd->entry_data.addr.msf.minute * 60) * 75;
+}
+
+int 
+vcd_seek_to_track(mp_vcd_priv_t* vcd, int track)
+{
+  vcd->entry.address_format = CD_MSF_FORMAT;
+  vcd->entry.starting_track = track;
+  vcd->entry.data_len = sizeof(struct cd_toc_entry);
+  vcd->entry.data = &vcd->entry_data;
+  if (ioctl(vcd->fd, CDIOREADTOCENTRIES, &vcd->entry)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif1: %s\n",strerror(errno));
+    return -1;
+  }
+  return VCD_SECTOR_DATA * vcd_get_msf(vcd);
+}
+
+int 
+vcd_get_track_end(mp_vcd_priv_t* vcd, int track)
+{
+  struct ioc_toc_header tochdr;
+  if (ioctl(vcd->fd, CDIOREADTOCHEADER, &tochdr) == -1) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+    return -1;
+  }
+  vcd->entry.address_format = CD_MSF_FORMAT;
+  vcd->entry.starting_track = track < tochdr.ending_track ? (track + 1) : CDROM_LEADOUT;
+  vcd->entry.data_len = sizeof(struct cd_toc_entry);
+  vcd->entry.data = &vcd->entry_data;
+  if (ioctl(vcd->fd, CDIOREADTOCENTRYS, &vcd->entry)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif2: %s\n",strerror(errno));
+    return -1;
+  }
+  return VCD_SECTOR_DATA * vcd_get_msf(vcd);
+}
+
+mp_vcd_priv_t*
+vcd_read_toc(int fd)
+{
+  struct ioc_toc_header tochdr;
+  mp_vcd_priv_t* vcd;
+  int             i;
+  if (ioctl(fd, CDIOREADTOCHEADER, &tochdr) == -1) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+    return;
+  }
+  for (i = tochdr.starting_track; i <= tochdr.ending_track; i++) {
+    struct ioc_read_toc_entry tocentry;
+    struct cd_toc_entry tocentry_data;
+
+    tocentry.starting_track = i;
+    tocentry.address_format = CD_MSF_FORMAT;
+    tocentry.data_len = sizeof(struct cd_toc_entry);
+    tocentry.data = &tocentry_data;
+
+    if (ioctl(fd, CDIOREADTOCENTRYS, &tocentry) == -1) {
+      mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc entry: %s\n",strerror(errno));
+      return NULL;
+    }
+    mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d:  adr=%d  ctrl=%d  format=%d  %02d:%02d:%02d\n",
+	   (int) tocentry.starting_track,
+	   (int) tocentry.data->addr_type,
+	   (int) tocentry.data->control,
+	   (int) tocentry.address_format,
+	   (int) tocentry.data->addr.msf.minute,
+	   (int) tocentry.data->addr.msf.second,
+	   (int) tocentry.data->addr.msf.frame
+      );
+  }
+  vcd = malloc(sizeof(mp_vcd_priv_t));
+  vcd->fd = fd;
+  return vcd;
+}
+
+static int 
+vcd_read(mp_vcd_priv_t* vcd, char *mem)
+{
+  struct scsireq  sc;
+  int             lba = vcd_get_msf(vcd);
+  int             blocks;
+  int             sector_type;
+  int             sync, header_code, user_data, edc_ecc, error_field;
+  int             sub_channel;
+  int             rc;
+
+  blocks = 1;
+  sector_type = 5;		/* mode2/form2 */
+  sync = 0;
+  header_code = 0;
+  user_data = 1;
+  edc_ecc = 0;
+  error_field = 0;
+  sub_channel = 0;
+
+  memset(&sc, 0, sizeof(sc));
+  sc.cmd[0] = 0xBE;
+  sc.cmd[1] = (sector_type) << 2;
+  sc.cmd[2] = (lba >> 24) & 0xff;
+  sc.cmd[3] = (lba >> 16) & 0xff;
+  sc.cmd[4] = (lba >> 8) & 0xff;
+  sc.cmd[5] = lba & 0xff;
+  sc.cmd[6] = (blocks >> 16) & 0xff;
+  sc.cmd[7] = (blocks >> 8) & 0xff;
+  sc.cmd[8] = blocks & 0xff;
+  sc.cmd[9] = (sync << 7) | (header_code << 5) | (user_data << 4) |
+    (edc_ecc << 3) | (error_field << 1);
+  sc.cmd[10] = sub_channel;
+  sc.cmdlen = 12;
+  sc.databuf = (caddr_t) mem;
+  sc.datalen = 2328;
+  sc.senselen = sizeof(sc.sense);
+  sc.flags = SCCMD_READ;
+  sc.timeout = 10000;
+  rc = ioctl(vcd->fd, SCIOCCOMMAND, &sc);
+  if (rc == -1) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"SCIOCCOMMAND: %s\n",strerror(errno));
+    return -1;
+  }
+  if (sc.retsts || sc.error) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"scsi command failed: status %d error %d\n",
+	   sc.retsts,sc.error);
+    return -1;
+  }
+  vcd_inc_msf(vcd);
+  return VCD_SECTOR_DATA;
+}
+
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.