Darwin: move specific files to a darwin/ folder
[vlc.git] / src / darwin / dirs.c
1 /*****************************************************************************
2  * darwin_dirs.c: Mac OS X directories configuration
3  *****************************************************************************
4  * Copyright (C) 2001-2009 VLC authors and VideoLAN
5  * Copyright © 2007-2012 Rémi Denis-Courmont
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *          Felix Paul Kühne <fkuehne at videolan dot org>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #include <CoreFoundation/CoreFoundation.h>
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32
33 #include "../libvlc.h"
34 #include <vlc_configuration.h>
35 #include "config/configuration.h"
36
37 #include <libgen.h>
38 #include <dlfcn.h>
39 #include <mach-o/dyld.h>
40
41 #ifndef MAXPATHLEN
42 # define MAXPATHLEN 1024
43 #endif
44
45 static char *config_GetLibPath (void)
46 {
47     /* Get the full program path and name */
48     /* First try to see if we are linked to the framework */
49     for (unsigned i = 0; i < _dyld_image_count(); i++)
50     {
51         const char *psz_img_name = _dyld_get_image_name(i);
52         const char *p = strstr( psz_img_name, "VLCKit.framework/Versions/" );
53
54         /* Check for "VLCKit.framework/Versions/Current/VLCKit",
55          * as well as "VLCKit.framework/Versions/A/VLCKit" and
56          * "VLC.framework/Versions/B/VLCKit" */
57         if( p != NULL )
58         {
59             /* Look for the next forward slash */
60             p += 26; /* p_char += strlen(" VLCKit.framework/Versions/" ) */
61             p += strcspn( p, "/" );
62
63             /* If the string ends with VLC then we've found a winner */
64             if ( !strcmp( p, "/VLCKit" ) )
65                 return strdup( psz_img_name );
66         }
67
68         /* Do we end by "VLC"? If so we are the legacy VLC.app that doesn't
69          * link to VLCKit. */
70         size_t len = strlen(psz_img_name);
71         if( len >= 3 && !strcmp( psz_img_name + len - 3, "VLC") )
72             return strdup( psz_img_name );
73     }
74
75     /* We are not linked to the VLC.framework, let's use dladdr to figure
76      * libvlc path */
77     Dl_info info;
78     if( dladdr(system_Init, &info) )
79         return strdup(dirname( info.dli_fname ));
80
81     char path[MAXPATHLEN+1];
82     uint32_t path_len = sizeof(path) - 1;
83
84     if ( !_NSGetExecutablePath(path, &path_len) )
85          return strdup(path);
86     return NULL;
87 }
88
89 char *config_GetLibDir (void)
90 {
91     char *path = config_GetLibPath ();
92     if (path != NULL)
93     {
94         char *p = strrchr (path, '/');
95         if (p != NULL)
96         {
97             *p = '\0';
98             return path;
99         }
100         free (path);
101     }
102
103     /* should never happen */
104     abort ();
105 }
106
107 char *config_GetDataDir (void)
108 {
109     const char *path = getenv ("VLC_DATA_PATH");
110     if (path)
111         return strdup (path);
112
113     char *vlcpath = config_GetLibDir ();
114     char *datadir;
115
116     if (asprintf (&datadir, "%s/share", vlcpath) == -1)
117         datadir = NULL;
118
119     free (vlcpath);
120     return datadir;
121 }
122
123 static char *config_GetHomeDir (void)
124 {
125     const char *home = getenv ("HOME");
126
127     if (home == NULL)
128         home = "/tmp";
129
130     return strdup (home);
131 }
132
133 static char *getAppDependentDir(vlc_userdir_t type)
134 {
135     const char *psz_path;
136     switch (type)
137     {
138         case VLC_CONFIG_DIR:
139             psz_path = "%s/Library/Preferences/%s";
140             break;
141         case VLC_TEMPLATES_DIR:
142         case VLC_DATA_DIR:
143             psz_path = "%s/Library/Application Support/%s";
144             break;
145         case VLC_CACHE_DIR:
146             psz_path = "%s/Library/Caches/%s";
147             break;
148         default:
149             assert(0);
150             break;
151     }
152
153     // Default fallback
154     const char *name = "org.videolan.vlc";
155
156     CFBundleRef mainBundle = CFBundleGetMainBundle();
157     if (mainBundle)
158     {
159         CFStringRef identifierAsNS = CFBundleGetIdentifier(mainBundle);
160         if (identifierAsNS)
161         {
162             char identifier[256];
163             Boolean ret = CFStringGetCString(identifierAsNS, identifier, sizeof(identifier), kCFStringEncodingUTF8);
164             if (ret)
165                 name = identifier;            
166         }
167     }
168
169     char *psz_parent = config_GetHomeDir ();
170     char *psz_dir;
171     if( asprintf( &psz_dir, psz_path, psz_parent, name) == -1 )
172         psz_dir = NULL;
173     free(psz_parent);
174
175     return psz_dir;    
176 }
177
178 char *config_GetUserDir (vlc_userdir_t type)
179 {
180     const char *psz_path;
181     switch (type)
182     {
183         case VLC_CONFIG_DIR:
184         case VLC_TEMPLATES_DIR:
185         case VLC_DATA_DIR:
186         case VLC_CACHE_DIR:
187             return getAppDependentDir(type);
188
189         case VLC_DESKTOP_DIR:
190             psz_path = "%s/Desktop";
191             break;
192         case VLC_DOWNLOAD_DIR:
193             psz_path = "%s/Downloads";
194             break;
195         case VLC_DOCUMENTS_DIR:
196             psz_path = "%s/Documents";
197             break;
198         case VLC_MUSIC_DIR:
199             psz_path = "%s/Music";
200             break;
201         case VLC_PICTURES_DIR:
202             psz_path = "%s/Pictures";
203             break;
204         case VLC_VIDEOS_DIR:
205             psz_path = "%s/Movies";
206             break;
207         case VLC_PUBLICSHARE_DIR:
208             psz_path = "%s/Public";
209             break;
210         case VLC_HOME_DIR:
211         default:
212             psz_path = "%s";
213     }
214     char *psz_parent = config_GetHomeDir ();
215     char *psz_dir;
216     if( asprintf( &psz_dir, psz_path, psz_parent ) == -1 )
217         psz_dir = NULL;
218     free(psz_parent);
219     return psz_dir;
220 }