7 #include "play_queue.h"
19 #include "ui_curses.h"
22 #include <sys/types.h>
30 static char **playable_exts
;
31 static const char * const playlist_exts
[] = { "m3u", "pl", "pls", NULL
};
35 playable_exts
= ip_get_supported_extensions();
44 worker_remove_jobs(JOB_TYPE_ANY
);
47 d_print("error: %s\n", strerror(errno
));
52 struct track_info
*info
;
55 info
= play_queue_remove();
58 info
= lib_set_next();
66 player_set_file(info
);
71 struct track_info
*info
;
75 info
= lib_set_prev();
82 player_set_file(info
);
85 void cmus_play_file(const char *filename
)
87 struct track_info
*ti
;
89 if (is_url(filename
)) {
90 ti
= track_info_url_new(filename
);
93 ti
= cache_get_ti(filename
);
96 error_msg("Couldn't get file information for %s\n", filename
);
100 player_play_file(ti
);
103 enum file_type
cmus_detect_ft(const char *name
, char **ret
)
109 *ret
= xstrdup(name
);
110 return FILE_TYPE_URL
;
114 absolute
= path_absolute(name
);
115 if (absolute
== NULL
)
116 return FILE_TYPE_INVALID
;
118 /* stat follows symlinks, lstat does not */
119 if (stat(absolute
, &st
) == -1) {
121 return FILE_TYPE_INVALID
;
124 if (S_ISDIR(st
.st_mode
)) {
126 return FILE_TYPE_DIR
;
128 if (!S_ISREG(st
.st_mode
)) {
131 return FILE_TYPE_INVALID
;
135 if (cmus_is_playlist(absolute
))
138 /* NOTE: it could be FILE_TYPE_PL too! */
139 return FILE_TYPE_FILE
;
142 void cmus_add(add_ti_cb add
, const char *name
, enum file_type ft
, int jt
)
144 struct add_data
*data
= xnew(struct add_data
, 1);
147 data
->name
= xstrdup(name
);
149 worker_add_job(jt
, do_add_job
, free_add_job
, data
);
152 static int save_playlist_cb(void *data
, struct track_info
*ti
)
154 int fd
= *(int *)data
;
155 const char nl
= '\n';
158 rc
= write_all(fd
, ti
->filename
, strlen(ti
->filename
));
161 rc
= write_all(fd
, &nl
, 1);
167 int cmus_save(for_each_ti_cb for_each_ti
, const char *filename
)
171 fd
= open(filename
, O_CREAT
| O_WRONLY
| O_TRUNC
, 0666);
174 rc
= for_each_ti(save_playlist_cb
, &fd
);
179 static int update_cb(void *data
, struct track_info
*ti
)
181 struct update_data
*d
= data
;
183 if (is_url(ti
->filename
))
186 if (d
->size
== d
->used
) {
190 d
->ti
= xrealloc(d
->ti
, d
->size
* sizeof(struct track_info
*));
193 d
->ti
[d
->used
++] = ti
;
197 void cmus_update_cache(void)
199 worker_add_job(JOB_TYPE_LIB
, do_update_cache_job
, free_update_cache_job
, NULL
);
202 void cmus_update_lib(void)
204 struct update_data
*data
;
206 data
= xnew(struct update_data
, 1);
212 lib_for_each(update_cb
, data
);
215 worker_add_job(JOB_TYPE_LIB
, do_update_job
, free_update_job
, data
);
218 void cmus_update_tis(struct track_info
**tis
, int nr
)
220 struct update_data
*data
;
222 data
= xnew(struct update_data
, 1);
226 worker_add_job(JOB_TYPE_LIB
, do_update_job
, free_update_job
, data
);
229 static const char *get_ext(const char *filename
)
231 const char *ext
= strrchr(filename
, '.');
238 static int str_in_array(const char *str
, const char * const *array
)
242 for (i
= 0; array
[i
]; i
++) {
243 if (strcasecmp(str
, array
[i
]) == 0)
249 int cmus_is_playlist(const char *filename
)
251 const char *ext
= get_ext(filename
);
253 return ext
&& str_in_array(ext
, playlist_exts
);
256 int cmus_is_playable(const char *filename
)
258 const char *ext
= get_ext(filename
);
260 return ext
&& str_in_array(ext
, (const char * const *)playable_exts
);
263 int cmus_is_supported(const char *filename
)
265 const char *ext
= get_ext(filename
);
267 return ext
&& (str_in_array(ext
, (const char * const *)playable_exts
) ||
268 str_in_array(ext
, playlist_exts
));
272 int (*cb
)(void *data
, const char *line
);
276 static int pl_handle_line(void *data
, const char *line
)
278 struct pl_data
*d
= data
;
281 while (isspace(line
[i
]))
289 return d
->cb(d
->data
, line
);
292 static int pls_handle_line(void *data
, const char *line
)
294 struct pl_data
*d
= data
;
296 if (strncasecmp(line
, "file", 4))
298 line
= strchr(line
, '=');
301 return d
->cb(d
->data
, line
+ 1);
304 int cmus_playlist_for_each(const char *buf
, int size
, int reverse
,
305 int (*cb
)(void *data
, const char *line
),
308 struct pl_data d
= { cb
, data
};
309 int (*handler
)(void *, const char *);
311 handler
= pl_handle_line
;
312 if (size
>= 10 && strncasecmp(buf
, "[playlist]", 10) == 0)
313 handler
= pls_handle_line
;
316 buffer_for_each_line_reverse(buf
, size
, handler
, &d
);
318 buffer_for_each_line(buf
, size
, handler
, &d
);