00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <limits.h>
00027 #include <unistd.h>
00028
00029 #ifdef _WIN32
00030 #include <windows.h>
00031 #endif
00032
00033 #ifdef HAVE_CONFIG_H
00034 # include "config.h"
00035 #endif
00036
00037 #include <glib.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include <ctype.h>
00041
00042 #include <errno.h>
00043
00044 #ifdef HAVE_FTS_H
00045 # include <sys/types.h>
00046 # include <sys/stat.h>
00047 # include <fts.h>
00048 #endif
00049
00050 #include <libaudcore/audstrings.h>
00051 #include <libaudcore/stringpool.h>
00052
00053 #include "audconfig.h"
00054 #include "debug.h"
00055 #include "i18n.h"
00056 #include "misc.h"
00057 #include "plugins.h"
00058 #include "util.h"
00059
00060 gboolean
00061 dir_foreach(const gchar * path, DirForeachFunc function,
00062 gpointer user_data, GError ** error)
00063 {
00064 GError *error_out = NULL;
00065 GDir *dir;
00066 const gchar *entry;
00067 gchar *entry_fullpath;
00068
00069 if (!(dir = g_dir_open(path, 0, &error_out))) {
00070 g_propagate_error(error, error_out);
00071 return FALSE;
00072 }
00073
00074 while ((entry = g_dir_read_name(dir))) {
00075 entry_fullpath = g_build_filename(path, entry, NULL);
00076
00077 if ((*function) (entry_fullpath, entry, user_data)) {
00078 g_free(entry_fullpath);
00079 break;
00080 }
00081
00082 g_free(entry_fullpath);
00083 }
00084
00085 g_dir_close(dir);
00086
00087 return TRUE;
00088 }
00089
00098 gchar*
00099 util_get_localdir(void)
00100 {
00101 gchar *datadir;
00102 gchar *tmp;
00103
00104 if ( (tmp = getenv("XDG_CONFIG_HOME")) == NULL )
00105 datadir = g_build_filename( g_get_home_dir() , ".config" , "audacious" , NULL );
00106 else
00107 datadir = g_build_filename( tmp , "audacious" , NULL );
00108
00109 return datadir;
00110 }
00111
00112
00113 gchar * construct_uri (const gchar * string, const gchar * playlist_name)
00114 {
00115 gchar *filename = g_strdup(string);
00116 gchar *uri = NULL;
00117
00118
00119 convert_dos_path(filename);
00120
00121
00122
00123 if (filename[0] == '/' || strstr(filename, "://")) {
00124 uri = g_filename_to_uri(filename, NULL, NULL);
00125 if(!uri)
00126 uri = g_strdup(filename);
00127 }
00128
00129
00130 else
00131 {
00132 const gchar * slash = strrchr (playlist_name, '/');
00133 if (slash)
00134 uri = g_strdup_printf ("%.*s/%s", (gint) (slash - playlist_name),
00135 playlist_name, filename);
00136 }
00137
00138 g_free (filename);
00139 return uri;
00140 }
00141
00142
00143 gint file_get_mtime (const gchar * filename)
00144 {
00145 struct stat info;
00146
00147 if (stat (filename, & info))
00148 return -1;
00149
00150 return info.st_mtime;
00151 }
00152
00153 void
00154 make_directory(const gchar * path, mode_t mode)
00155 {
00156 if (g_mkdir_with_parents(path, mode) == 0)
00157 return;
00158
00159 g_printerr(_("Could not create directory (%s): %s\n"), path,
00160 g_strerror(errno));
00161 }
00162
00163 gchar * get_path_to_self (void)
00164 {
00165 gchar buf[PATH_MAX];
00166 gint len;
00167
00168 #ifdef _WIN32
00169 if (! (len = GetModuleFileName (NULL, buf, sizeof buf)) || len == sizeof buf)
00170 {
00171 fprintf (stderr, "GetModuleFileName failed.\n");
00172 return NULL;
00173 }
00174 #else
00175 if ((len = readlink ("/proc/self/exe", buf, sizeof buf)) < 0)
00176 {
00177 fprintf (stderr, "Cannot access /proc/self/exe: %s.\n", strerror (errno));
00178 return NULL;
00179 }
00180 #endif
00181
00182 return g_strndup (buf, len);
00183 }
00184
00185 #define URL_HISTORY_MAX_SIZE 30
00186
00187 void
00188 util_add_url_history_entry(const gchar * url)
00189 {
00190 if (g_list_find_custom(cfg.url_history, url, (GCompareFunc) strcasecmp))
00191 return;
00192
00193 cfg.url_history = g_list_prepend(cfg.url_history, g_strdup(url));
00194
00195 while (g_list_length(cfg.url_history) > URL_HISTORY_MAX_SIZE) {
00196 GList *node = g_list_last(cfg.url_history);
00197 g_free(node->data);
00198 cfg.url_history = g_list_delete_link(cfg.url_history, node);
00199 }
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 static gchar * skip_top_folders (gchar * name)
00211 {
00212 const gchar * home = getenv ("HOME");
00213 if (! home)
00214 goto NO_HOME;
00215
00216 gint len = strlen (home);
00217 if (len > 0 && home[len - 1] == G_DIR_SEPARATOR)
00218 len --;
00219
00220 #ifdef _WIN32
00221 if (! strncasecmp (name, home, len) && name[len] == '\\')
00222 #else
00223 if (! strncmp (name, home, len) && name[len] == '/')
00224 #endif
00225 return name + len + 1;
00226
00227 NO_HOME:
00228 #ifdef _WIN32
00229 return (name[0] && name[1] == ':' && name[2] == '\\') ? name + 3 : name;
00230 #else
00231 return (name[0] == '/') ? name + 1 : name;
00232 #endif
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 static void split_filename (gchar * name, gchar * * base, gchar * * first,
00244 gchar * * second)
00245 {
00246 * first = * second = NULL;
00247
00248 gchar * c;
00249
00250 if ((c = strrchr (name, G_DIR_SEPARATOR)))
00251 {
00252 * base = c + 1;
00253 * c = 0;
00254 }
00255 else
00256 {
00257 * base = name;
00258 goto DONE;
00259 }
00260
00261 if ((c = strrchr (name, G_DIR_SEPARATOR)))
00262 {
00263 * first = c + 1;
00264 * c = 0;
00265 }
00266 else
00267 {
00268 * first = name;
00269 goto DONE;
00270 }
00271
00272 if ((c = strrchr (name, G_DIR_SEPARATOR)))
00273 * second = c + 1;
00274 else
00275 * second = name;
00276
00277 DONE:
00278 if ((c = strrchr (* base, '.')))
00279 * c = 0;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288 static gchar * stream_name (gchar * name)
00289 {
00290 if (! strncmp (name, "http://", 7))
00291 name += 7;
00292 else if (! strncmp (name, "https://", 8))
00293 name += 8;
00294 else if (! strncmp (name, "mms://", 6))
00295 name += 6;
00296 else
00297 return NULL;
00298
00299 gchar * c;
00300
00301 if ((c = strchr (name, '/')))
00302 * c = 0;
00303 if ((c = strchr (name, ':')))
00304 * c = 0;
00305 if ((c = strchr (name, '?')))
00306 * c = 0;
00307
00308 return name;
00309 }
00310
00311
00312
00313
00314 void describe_song (const gchar * name, const Tuple * tuple, gchar * * _title,
00315 gchar * * _artist, gchar * * _album)
00316 {
00317
00318 static const gchar * const skip[] = {"music"};
00319
00320 const gchar * title = tuple_get_string (tuple, FIELD_TITLE, NULL);
00321 const gchar * artist = tuple_get_string (tuple, FIELD_ARTIST, NULL);
00322 const gchar * album = tuple_get_string (tuple, FIELD_ALBUM, NULL);
00323
00324 if (title && ! title[0])
00325 title = NULL;
00326 if (artist && ! artist[0])
00327 artist = NULL;
00328 if (album && ! album[0])
00329 album = NULL;
00330
00331 gchar * copy = NULL;
00332
00333 if (title && artist && album)
00334 goto DONE;
00335
00336 copy = uri_to_display (name);
00337
00338 if (! strncmp (name, "file://", 7))
00339 {
00340 gchar * base, * first, * second;
00341 split_filename (skip_top_folders (copy), & base, & first,
00342 & second);
00343
00344 if (! title)
00345 title = base;
00346
00347 for (gint i = 0; i < G_N_ELEMENTS (skip); i ++)
00348 {
00349 if (first && ! strcasecmp (first, skip[i]))
00350 first = NULL;
00351 if (second && ! strcasecmp (second, skip[i]))
00352 second = NULL;
00353 }
00354
00355 if (first)
00356 {
00357 if (second && ! artist && ! album)
00358 {
00359 artist = second;
00360 album = first;
00361 }
00362 else if (! artist)
00363 artist = first;
00364 else if (! album)
00365 album = first;
00366 }
00367 }
00368 else
00369 {
00370 if (! title)
00371 title = stream_name (copy);
00372 else if (! artist)
00373 artist = stream_name (copy);
00374 else if (! album)
00375 album = stream_name (copy);
00376 }
00377
00378 DONE:
00379 * _title = title ? stringpool_get ((gchar *) title, FALSE) : NULL;
00380 * _artist = artist ? stringpool_get ((gchar *) artist, FALSE) : NULL;
00381 * _album = album ? stringpool_get ((gchar *) album, FALSE) : NULL;
00382
00383 g_free (copy);
00384 }