1 /*
2 * This file is part of MPlayer.
3 *
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 /**
20 * @file
21 * @brief Miscellaneous utilities
22 */
23
24 #include <ctype.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "misc.h"
30 #include "string.h"
31 #include "gui/app/gui.h"
32
33 #define CFG_OLD_PLAYLIST
34 #include "gui/app/cfg-old.c"
35
36 #include "mp_msg.h"
37
38 /**
39 * @brief Read characters from @a file.
40 *
41 * @param str memory location of a buffer to receive the read characters
42 * @param size number of characters read at the most (including a terminating null-character)
43 * @param file file to read from
44 *
45 * @return str (success) or NULL (error)
46 *
47 * @note Reading stops with an end-of-line character or at end of file.
48 */
fgetstr(char * str,int size,FILE * file)49 char *fgetstr(char *str, int size, FILE *file)
50 {
51 char *s;
52
53 s = fgets(str, size, file);
54
55 if (s)
56 s[strcspn(s, "\n\r")] = 0;
57
58 return s;
59 }
60
61 /**
62 * @brief Constrain a @a value to be in the range of 0 to 100.
63 *
64 * @param value value to be checked
65 *
66 * @return a value in the range of 0 to 100
67 */
constrain(float value)68 float constrain(float value)
69 {
70 if (value < 0.0f)
71 return 0.0f;
72 if (value > 100.0f)
73 return 100.0f;
74
75 return value;
76 }
77
78 /**
79 * @brief Convert MM:SS:FF (minute/second/frame) to seconds.
80 *
81 * @param msf string in MM:SS:FF format
82 *
83 * @return seconds equivalent to @a msf (0 in case of error)
84 */
msf2sec(const char * msf)85 float msf2sec(const char *msf)
86 {
87 int i;
88
89 for (i = 0; i < 8; i++)
90 switch (i) {
91 case 0:
92 case 1:
93 case 3:
94 case 4:
95 case 6:
96 case 7:
97 if (!isdigit(msf[i]))
98 return 0.0f;
99 break;
100
101 case 2:
102 case 5:
103 if (msf[i] != ':')
104 return 0.0f;
105 break;
106 }
107
108 return (msf[0] - '0') * 600 + (msf[1] - '0') * 60 +
109 (msf[3] - '0') * 10 + (msf[4] - '0') +
110 ((msf[6] - '0') * 10 + (msf[7] - '0')) / 75.0f;
111 }
112
113 /**
114 * @brief Analyze a cue file whether it describes a disc image (binary data)
115 * or a playlist for data files containing multiple titles.
116 *
117 * @param fname cue file to be analyzed
118 *
119 * @return pointer to an array of playlist items or NULL (binary data or error)
120 */
cue_playlist(const char * fname)121 plItem **cue_playlist(const char *fname)
122 {
123 static plItem *item[101];
124 FILE *file;
125 char line[256], *l, *fmt, *path = NULL, *data = NULL;
126 int i = -1, isFILE = False, isTRACK = False;
127
128 file = fopen(fname, "rt");
129
130 if (file)
131 mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[misc] cue file: %s\n", fname);
132 else
133 return NULL;
134
135 memset(item, 0, sizeof(item));
136
137 while (fgetstr(line, sizeof(line), file) && (i < 99)) {
138 l = (char *)ltrim(line);
139
140 if (strncmp(l, "FILE ", 5) == 0) {
141 fmt = strrchr(l, ' ');
142
143 if (strcmp(fmt + 1, "BINARY") == 0) {
144 mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[misc] cue file describes BINARY (bin/cue)\n");
145 break;
146 }
147
148 *fmt = 0;
149
150 setdup(&data, dequote(l + 5));
151 mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[misc] cue file data: %s (%s)\n", data, fmt + 1);
152
153 if (strrchr(data, '/')) {
154 setdup(&path, data);
155 l = strrchr(path, '/');
156 *l = 0;
157 setdup(&data, l + 1);
158 } else {
159 setdup(&path, fname);
160 l = strrchr(path, '/');
161
162 if (l)
163 *l = 0;
164 else
165 setdup(&path, ".");
166 }
167
168 isFILE = True;
169 } else if (strncmp(l, "TRACK ", 6) == 0) {
170 if (!isFILE)
171 continue;
172
173 item[++i] = calloc(1, sizeof(**item));
174
175 if (!item[i])
176 break;
177
178 item[i]->path = strdup(cfg_old_filename_from_utf8(path));
179 item[i]->name = strdup(cfg_old_filename_from_utf8(data));
180
181 isTRACK = True;
182 } else if (strncmp(l, "TITLE ", 6) == 0) {
183 if (!isTRACK)
184 continue;
185
186 item[i]->title = strdup(dequote(l + 6));
187 } else if (strncmp(l, "INDEX 01 ", 9) == 0) {
188 if (!isTRACK)
189 continue;
190
191 item[i]->start = msf2sec(l + 9);
192
193 mp_msg(MSGT_GPLAYER, MSGL_V, "[misc] cue file data track %02d starts at %s\n", i + 1, l + 9);
194 }
195 }
196
197 free(path);
198 free(data);
199 fclose(file);
200
201 return (i == -1 ? NULL : item);
202 }
203