chiark / gitweb /
lib.c: Remove redundant format attributes.
[dvdrip] / lib.c
1 #include "lib.h"
2
3 const char *prog = "<unset>";
4
5 void set_prog(const char *p)
6   { const char *q = strrchr(p, '/'); prog = q ? q + 1 : p; }
7
8 void vmoan(const char *fmt, va_list ap)
9   { fprintf(stderr, "%s: ", prog); vfprintf(stderr, fmt, ap); }
10
11 void moan(const char *fmt, ...)
12 {
13   va_list ap;
14
15   va_start(ap, fmt); vmoan(fmt, ap); va_end(ap);
16   fputc('\n', stderr);
17 }
18
19 void bail(const char *fmt, ...)
20 {
21   va_list ap;
22
23   va_start(ap, fmt); vmoan(fmt, ap); va_end(ap);
24   fputc('\n', stderr);
25   exit(2);
26 }
27
28 void bail_syserr(int err, const char *fmt, ...)
29 {
30   va_list ap;
31
32   va_start(ap, fmt); vmoan(fmt, ap); va_end(ap);
33   if (err) fprintf(stderr, ": %s", strerror(errno));
34   fputc('\n', stderr);
35   exit(2);
36 }
37
38 void sit(double t)
39 {
40   struct timeval tv;
41   double whole = floor(t);
42
43   if (t) {
44     tv.tv_sec = whole; tv.tv_usec = floor((t - whole)*1.0e6) + 1;
45     if (select(0, 0, 0, 0, &tv) < 0) bail_syserr(errno, "failed to sleep");
46   }
47 }
48
49 void carefully_write(int fd, const void *buf, size_t sz)
50 {
51   const unsigned char *p = buf;
52   ssize_t n;
53
54   if (fd < 0) return;
55   while (sz) {
56     n = write(fd, p, sz);
57     if (n < 0) {
58       if (errno == EINTR) continue;
59       bail_syserr(errno, "failed to write to output file");
60     }
61     if (!n) bail("unexpected short write to output file");
62     p += n; sz -= n;
63   }
64 }
65
66 void open_file_on_demand(const char *file, FILE **fp_inout, const char *what)
67 {
68   FILE *fp;
69
70   if (!*fp_inout) {
71     fp = fopen(file, "w");
72     if (!fp) bail_syserr(errno, "failed to open %s file `%s'", what, file);
73     fprintf(fp, "## %s\n\n", what);
74     *fp_inout = fp;
75   }
76 }
77
78 void check_write(FILE *fp, const char *what)
79 {
80   fflush(fp);
81   if (ferror(fp)) bail_syserr(errno, "error writing %s file", what);
82 }
83
84 void carefully_fclose(FILE *fp, const char *what)
85 {
86   if (fp && (ferror(fp) || fclose(fp)))
87     bail_syserr(errno, "error writing %s file", what);
88 }
89
90 void store_filename(char *buf, ident id)
91 {
92   switch (id_kind(id)) {
93     case RAW:
94       sprintf(buf, "#<raw device>");
95       break;
96     case IFO:
97       if (!id_title(id)) sprintf(buf, "/VIDEO_TS/VIDEO_TS.IFO");
98       else sprintf(buf, "/VIDEO_TS/VTS_%02u_0.IFO", id_title(id));
99       break;
100     case BUP:
101       if (!id_title(id)) sprintf(buf, "/VIDEO_TS/VIDEO_TS.BUP");
102       else sprintf(buf, "/VIDEO_TS/VTS_%02u_0.BUP", id_title(id));
103       break;
104     case VOB:
105       if (!id_title(id)) sprintf(buf, "/VIDEO_TS/VIDEO_TS.VOB");
106       else
107         sprintf(buf, "/VIDEO_TS/VTS_%02u_%u.VOB", id_title(id), id_part(id));
108       break;
109     default:
110       abort();
111   }
112 }
113
114 struct progress_state progress = PROGRESS_STATE_INIT;
115 static struct banner_progress_item banner_progress;
116
117 static void render_banner_progress(struct progress_item *item,
118                             struct progress_render_state *render)
119 {
120   struct banner_progress_item *bi = (struct banner_progress_item *)item;
121
122   progress_putleft(render, " %s", bi->msg);
123   progress_shownotice(render, 4, 7);
124 }
125
126 void show_banner(const char *msg)
127 {
128   banner_progress._base.render = render_banner_progress;
129   progress_additem(&progress, &banner_progress._base);
130   banner_progress.msg = msg;
131   progress_update(&progress);
132 }
133
134 void hide_banner(void)
135 {
136   if (!progress_removeitem(&progress, &banner_progress._base))
137     progress_update(&progress);
138 }
139
140 #ifdef notdef
141 static void logfn(void *p, dvd_logger_level_t lev,
142                   const char *fmt, va_list ap)
143 {
144   switch (lev) {
145     case DVD_LOGGER_LEVEL_ERROR:
146       fprintf("%s (libdvdread error): ", prog);
147       break;
148     case DVD_LOGGER_LEVEL_WARN:
149       fprintf("%s (libdvdread warning): ", prog);
150       break;
151     default:
152       return;
153   }
154   vfprintf(stderr, fmt, ap);
155   fputc('\n', stderr);
156 }
157 static const dvd_logger_cb logger = { logfn };
158 #endif
159
160 void open_dvd(const char *device, int *fd_out, dvd_reader_t **dvd_out)
161 {
162   int fd;
163   dvd_reader_t *dvd;
164   int bannerp = 0;
165
166   for (;;) {
167     fd = open(device, O_RDONLY);
168     if (fd >= 0 || errno != ENOMEDIUM) break;
169     if (!bannerp) {
170       show_banner("Waiting for disc to be inserted...");
171       bannerp = 1;
172     }
173     sit(0.2);
174   }
175   if (bannerp) hide_banner();
176   if (fd < 0) bail_syserr(errno, "failed to open device `%s'", device);
177   if (dvd_out) {
178 #ifdef notdef
179     dvd = DVDOpen2(0, &logger, device);
180 #else
181     dvd = DVDOpen(device);
182 #endif
183     if (!dvd) bail("failed to open DVD on `%s'", device);
184     *dvd_out = dvd;
185   }
186   if (fd_out) *fd_out = fd;
187   else close(fd);
188 }