6cee134209e6d4190325670b8eb84567eabd39da
[mikachu/openbox.git] / tools / xdg-autostart / xdg-autostart
1 #!/usr/bin/env python
2
3 # xdg-autostart runs things based on the XDG autostart specification
4 # Copyright (C) 2008       Dana Jansens
5 #
6 # XDG autostart specification can be found here:
7 # http://standards.freedesktop.org/autostart-spec/
8 #
9 #
10 #
11 # LICENSE:
12 #   This program is free software; you can redistribute it and/or modify
13 #   it under the terms of the GNU General Public License as published by
14 #   the Free Software Foundation; either version 2 of the License, or
15 #   (at your option) any later version.
16 #
17 #   This program is distributed in the hope that it will be useful,
18 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
19 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 #   GNU General Public License for more details.
21
22 ME="xdg-autostart"
23 VERSION="1.0"
24
25 from xdg import BaseDirectory
26 from xdg.DesktopEntry import DesktopEntry
27 from xdg.Exceptions import ParsingError
28 import os, glob, sys
29
30 def main(argv=sys.argv):
31     if "--help" in argv[1:]:
32         show_help()
33         return 0
34     if "--version" in argv[1:]:
35         show_version()
36         return 0
37
38     # get the autostart directories
39     autodirs = BaseDirectory.load_config_paths("autostart")
40
41     # find all the autostart files
42     files = []
43     for dir in autodirs:
44         for path in glob.glob(os.path.join(dir, '*.desktop')):
45             try:
46                 autofile = AutostartFile(path)
47             except ParsingError:
48                 print "Invalid .desktop file: " + path
49             else:
50                 if not autofile in files:
51                     files.append(autofile)
52
53     list = False
54     if "--list" in argv[1:]:
55         list = True
56         argv.remove("--list")
57
58     # run them !
59     environments = argv[1:]
60     for autofile in files:
61         if list: autofile.list(environments)
62         else: autofile.run(environments)
63
64 class AutostartFile():
65     def __init__(self, path):
66         self.path = path
67         self.filename = os.path.basename(path)
68         self.dirname = os.path.dirname(path)
69         self.de = DesktopEntry(path)
70
71     def __eq__(self, other):
72         return self.filename == other.filename
73
74     def __str__(self):
75         return self.path + " : " + self.de.getName()
76
77     def isexecfile(path):
78         return os.access(path, os.X_OK)
79
80     def findFile(self, path, search, match_func):
81         # check empty path
82         if not path: return None
83         # check absolute path
84         if path[0] == '/':
85             if match_func(path): return path
86             else: return None
87             # check relative path
88             for dirname in search.split(os.pathsep):
89                 if dirname != "":
90                     candidate = os.path.join(dirname, path)
91                     if (match_func(candidate)): return candidate
92
93     def alert(self, str, info=False):
94         if info:
95             print "\t ", str
96         else:
97             print "\t*", str
98
99     def showInEnvironment(self, envs, verbose=False):
100         default = not self.de.getOnlyShowIn()
101         noshow = False
102         force = False
103         for i in self.de.getOnlyShowIn():
104             if i in envs: force = True
105         for i in self.de.getNotShowIn():
106             if i in envs: noshow = True
107
108         if verbose:
109             if not default and not force:
110                 s = ""
111                 for i in self.de.getOnlyShowIn():
112                     if s: s += ", "
113                     s += i
114                 self.alert("Excluded by: OnlyShowIn (" + s + ")")
115             if default and noshow and not force:
116                 s = ""
117                 for i in self.de.getOnlyShowIn():
118                     if s: s += ", "
119                     s += i
120                 self.alert("Excluded by: NotShowIn (" + s + ")")
121         return (default and not noshow) or force
122
123     def shouldRun(self, envs, verbose=False):
124         if not self.de.getExec():
125             if verbose: self.alert("Excluded by: Missing Exec field")
126             return False
127         if self.de.getHidden():
128             if verbose: self.alert("Excluded by: Hidden")
129             return False
130         if self.de.getTryExec():
131             if not self.findFile(self.de.getTryExec(), os.getenv("PATH"),
132                                  self.isexecfile):
133                 if verbose: self.alert("Excluded by: TryExec (" +
134                                           self.de.getTryExec() + ")")
135                 return False
136         if not self.showInEnvironment(envs, verbose):
137             return False
138         return True
139
140     def list(self, envs):
141         running = False
142         if self.shouldRun(envs):
143             print "[*] " + self.de.getName()
144         else:
145             print "[ ] " + self.de.getName()
146         self.alert("File: " + self.path, info=True)
147         if self.de.getExec():
148             self.alert("Executes: " + self.de.getExec(), info=True)
149         self.shouldRun(envs, True)
150         print
151
152     def run(self, envs):
153         here = os.getcwd()
154         if self.de.getPath():
155             os.chdir(self.de.getPath())
156         if self.shouldRun(envs):
157             print "Running autostart file: " + self.path
158             os.system(self.de.getExec());
159         os.chdir(here)
160
161 def show_help():
162     print "Usage:", ME, "[OPTION]... [ENVIRONMENT]..."
163     print
164     print "This tool will run xdg autostart .desktop files"
165     print
166     print "OPTIONS"
167     print "  --list        Show a list of the files which would be run"
168     print "                Files which would be run are marked with an asterix"
169     print "                symbol [*].  For files which would not be run,"
170     print "                information is given for why they are excluded"
171     print "  --help        Show this help and exit"
172     print "  --version     Show version and copyright information"
173     print
174     print "ENVIRONMENT specifies a list of environments for which to run autostart"
175     print "applications for.  If none are specified, only applications which do not "
176     print "limit themselves to certain environments will be run."
177     print
178     print "ENVIRONMENT can be one or more of:"
179     print "  GNOME         Gnome Desktop"
180     print "  KDE           KDE Desktop"
181     print "  ROX           ROX Desktop"
182     print "  XFCE          XFCE Desktop"
183     print "  Old           Legacy systems"
184     print
185
186 def show_version():
187     print ME, VERSION
188     print "Copyright (c) 2008        Dana Jansens"
189     print
190
191 if __name__ == "__main__":
192         sys.exit(main())