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