Commit | Line | Data |
---|---|---|
dc53ebfa MW |
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 | ||
dc53ebfa MW |
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 | ||
dc53ebfa MW |
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 | ||
dc53ebfa MW |
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 | ||
00a5be1d MW |
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 | ||
dc53ebfa MW |
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 | } |