lol

miro: New package, version 6.0.

I actually had this breeding in my nixpkgs overrides for a year and only
recently took the time to fix it and thus revive my video feeds :-)

The package uses a patch which is removing the dependency on gconf and
switches to storage within a shelve in ~/.miro/config instead.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>

aszlig df4a3cc9 aa018de6

+454
+76
pkgs/applications/video/miro/default.nix
··· 1 + { stdenv, fetchurl, python, buildPythonPackage, pythonPackages, pkgconfig 2 + , pyrex096, ffmpeg, boost, glib, pygobject, gtk2, webkit_gtk2, libsoup, pygtk 3 + , taglib, pysqlite, pycurl, mutagen, pycairo, pythonDBus, pywebkitgtk 4 + , libtorrentRasterbar 5 + , gst_python, gst_plugins_base, gst_plugins_good, gst_ffmpeg 6 + }: 7 + 8 + buildPythonPackage rec { 9 + name = "miro-${version}"; 10 + namePrefix = ""; 11 + version = "6.0"; 12 + 13 + src = fetchurl { 14 + url = "http://ftp.osuosl.org/pub/pculture.org/miro/src/${name}.tar.gz"; 15 + sha256 = "0sq25w365i1fz95398vxql3yjl5i6mq77mnmlhmn0pgyg111k3am"; 16 + }; 17 + 18 + setSourceRoot = '' 19 + sourceRoot=${name}/linux 20 + ''; 21 + 22 + patches = [ ./gconf.patch ]; 23 + 24 + postPatch = '' 25 + sed -i -e '2i import os; os.environ["GST_PLUGIN_PATH"] = \\\ 26 + '"'$GST_PLUGIN_PATH'" miro.real 27 + 28 + sed -i -e 's/\$(shell which python)/python/' Makefile 29 + sed -i -e 's|/usr/bin/||' -e 's|/usr||' \ 30 + -e 's/BUILD_TIME[^,]*/BUILD_TIME=0/' setup.py 31 + 32 + sed -i -e 's|default="/usr/bin/ffmpeg"|default="${ffmpeg}/bin/ffmpeg"|' \ 33 + plat/options.py 34 + 35 + sed -i -e 's|/usr/share/miro/themes|'"$out/share/miro/themes"'|' \ 36 + -e 's/gnome-open/xdg-open/g' \ 37 + -e '/RESOURCE_ROOT =.*(/,/)/ { 38 + c RESOURCE_ROOT = '"'$out/share/miro/resources/'"' 39 + }' \ 40 + plat/resources.py 41 + ''; 42 + 43 + installCommand = '' 44 + python setup.py install --prefix= --root="$out" 45 + ''; 46 + 47 + # Disabled for now, because it requires networking and even if we skip those 48 + # tests, the whole test run takes around 10-20 minutes. 49 + doCheck = false; 50 + checkPhase = '' 51 + HOME="$TEMPDIR" LANG=en_US.UTF-8 python miro.real --unittest 52 + ''; 53 + 54 + postInstall = '' 55 + mv "$out/bin/miro.real" "$out/bin/miro" 56 + ''; 57 + 58 + buildInputs = [ 59 + pkgconfig pyrex096 ffmpeg boost glib pygobject gtk2 webkit_gtk2 libsoup 60 + pygtk taglib 61 + ]; 62 + 63 + propagatedBuildInputs = [ 64 + pygobject pygtk pycurl python.modules.sqlite3 mutagen pycairo pythonDBus 65 + pywebkitgtk libtorrentRasterbar 66 + gst_python gst_plugins_base gst_plugins_good gst_ffmpeg 67 + ]; 68 + 69 + meta = { 70 + homepage = "http://www.getmiro.com/"; 71 + description = "Video and audio feed aggregator"; 72 + license = stdenv.lib.licenses.gpl2Plus; 73 + maintainers = [ stdenv.lib.maintainers.aszlig ]; 74 + platforms = stdenv.lib.platforms.linux; 75 + }; 76 + }
+374
pkgs/applications/video/miro/gconf.patch
··· 1 + diff --git a/plat/associate.py b/plat/associate.py 2 + index 0f3cd31..f9b5a76 100644 3 + --- a/plat/associate.py 4 + +++ b/plat/associate.py 5 + @@ -31,69 +31,8 @@ 6 + Holds functions that associate Miro with certain protocols 7 + """ 8 + 9 + -import gconf 10 + -from miro.plat.config import gconf_lock 11 + - 12 + def associate_protocols(command): 13 + - _associate_protocol("magnet", command, False) 14 + + pass 15 + 16 + def disassociate_protocols(command): 17 + - _disassociate_protocol("magnet", command) 18 + - 19 + -def _associate_protocol(name, command, overwrite_existing=False): 20 + - url_handlers_key = "/desktop/gnome/url-handlers/" + name + "/" 21 + - if not _is_associated(name) or overwrite_existing: 22 + - gconf_lock.acquire() 23 + - try: 24 + - gconf_client = gconf.client_get_default() 25 + - if gconf_client.set_string(url_handlers_key + "command", command): 26 + - gconf_client.set_bool(url_handlers_key + "needs_terminal", False) 27 + - gconf_client.set_bool(url_handlers_key + "enabled", True) 28 + - success = True 29 + - else: 30 + - success = False 31 + - finally: 32 + - gconf_lock.release() 33 + - else: 34 + - success = True 35 + - return success 36 + - 37 + -def _disassociate_protocol(name, command): 38 + - url_handlers_key = "/desktop/gnome/url-handlers/" + name + "/" 39 + - if _is_associated(name, command): 40 + - gconf_lock.acquire() 41 + - try: 42 + - gconf_client = gconf.client_get_default() 43 + - if gconf_client.set_bool(url_handlers_key + "enabled", False): 44 + - success = True 45 + - else: 46 + - success = False 47 + - finally: 48 + - gconf_lock.release() 49 + - else: 50 + - success = True 51 + - return success 52 + - 53 + -def _is_associated(protocol, command=None): 54 + - """ Checks whether a protocol currently is 55 + - associated with the given command, or, 56 + - if none is given, whether the protocol 57 + - is associated with anything at all. 58 + - """ 59 + - url_handlers_key = "/desktop/gnome/url-handlers/" + protocol + "/" 60 + - gconf_lock.acquire() 61 + - try: 62 + - gconf_client = gconf.client_get_default() 63 + - key = gconf_client.get(url_handlers_key + "command") 64 + - if key is None: 65 + - associated = False 66 + - else: 67 + - enabled = gconf_client.get(url_handlers_key + "enabled") 68 + - if command: 69 + - associated = key.get_string() == command and enabled.get_bool() 70 + - else: 71 + - associated = key.get_string() != "" and enabled.get_bool() 72 + - finally: 73 + - gconf_lock.release() 74 + - return associated 75 + - 76 + + pass 77 + diff --git a/plat/config.py b/plat/config.py 78 + index 40895af..24f8815 100644 79 + --- a/plat/config.py 80 + +++ b/plat/config.py 81 + @@ -39,51 +39,20 @@ Preferences are listed in miro.pref and also miro.plat.options. 82 + import os 83 + import logging 84 + from miro import prefs 85 + -import gconf 86 + +import shelve 87 + import threading 88 + from miro.plat import options 89 + from miro.plat import resources 90 + 91 + -client = gconf.client_get_default() 92 + -gconf_lock = threading.RLock() 93 + - 94 + - 95 + -def gconf_key(key): 96 + - if options.gconf_name is None: 97 + - options.gconf_name = "miro" 98 + - return '/apps/%s/%s' % (options.gconf_name, key) 99 + - 100 + - 101 + -def _convert_gconf_value(value): 102 + - if value.type == gconf.VALUE_STRING: 103 + - return value.get_string() 104 + - if value.type == gconf.VALUE_INT: 105 + - return value.get_int() 106 + - if value.type == gconf.VALUE_BOOL: 107 + - return value.get_bool() 108 + - if value.type == gconf.VALUE_FLOAT: 109 + - return value.get_float() 110 + - if value.type == gconf.VALUE_LIST: 111 + - return [_convert_gconf_value(v) for v in value.get_list()] 112 + - raise TypeError("unknown gconf type %s" % value.type) 113 + - 114 + - 115 + -def _get_gconf(fullkey, default=None): 116 + - gconf_lock.acquire() 117 + - try: 118 + - value = client.get(fullkey) 119 + - if value != None: 120 + - try: 121 + - return _convert_gconf_value(value) 122 + - except TypeError, e: 123 + - logging.warn("type error while getting gconf value %s: %s", 124 + - fullkey, str(e)) 125 + - return default 126 + - finally: 127 + - gconf_lock.release() 128 + - 129 + - 130 + -class GconfDict: 131 + + 132 + +class ConfigFile(object): 133 + + def __init__(self): 134 + + support_dir = get(prefs.SUPPORT_DIRECTORY) 135 + + if not os.path.exists(support_dir): 136 + + os.makedirs(support_dir) 137 + + path = os.path.join(support_dir, 'config') 138 + + self.conf = shelve.open(path, 'c', -1, True) 139 + + 140 + def get(self, key, default=None): 141 + if not isinstance(key, str): 142 + raise TypeError() 143 + @@ -91,19 +56,16 @@ class GconfDict: 144 + if "MIRO_%s" % key.upper() in os.environ: 145 + return os.environ["MIRO_%s" % key.upper()] 146 + 147 + - fullkey = gconf_key(key) 148 + - return _get_gconf(fullkey, default) 149 + + return self.conf.get(key, default) 150 + + 151 + + def __del__(self): 152 + + self.conf.close() 153 + 154 + def __contains__(self, key): 155 + if "MIRO_%s" % key.upper() in os.environ: 156 + return True 157 + 158 + - gconf_lock.acquire() 159 + - try: 160 + - fullkey = gconf_key(key) 161 + - return client.get(fullkey) is not None 162 + - finally: 163 + - gconf_lock.release() 164 + + return key in self.conf 165 + 166 + def __getitem__(self, key): 167 + rv = self.get(key) 168 + @@ -116,43 +78,11 @@ class GconfDict: 169 + if "MIRO_%s" % key.upper() in os.environ: 170 + return 171 + 172 + - gconf_lock.acquire() 173 + - try: 174 + - if not isinstance(key, str): 175 + - raise TypeError() 176 + - 177 + - fullkey = gconf_key(key) 178 + - if isinstance(value, str): 179 + - client.set_string(fullkey, value) 180 + - elif isinstance(value, bool): 181 + - client.set_bool(fullkey, value) 182 + - elif isinstance(value, int): 183 + - client.set_int(fullkey, value) 184 + - elif isinstance(value, float): 185 + - client.set_float(fullkey, value) 186 + - elif isinstance(value, list): 187 + - # this is lame, but there isn't enough information to 188 + - # figure it out another way 189 + - if len(value) == 0 or isinstance(value[0], str): 190 + - list_type = gconf.VALUE_STRING 191 + - elif isinstance(value[0], int): 192 + - list_type = gconf.VALUE_INT 193 + - elif isinstance(value[0], float): 194 + - list_type = gconf.VALUE_FLOAT 195 + - elif isinstance(value[0], bool): 196 + - list_type = gconf.VALUE_BOOL 197 + - else: 198 + - raise TypeError("unknown gconf type %s" % type(value[0])) 199 + - 200 + - client.set_list(fullkey, list_type, value) 201 + - else: 202 + - raise TypeError() 203 + - finally: 204 + - gconf_lock.release() 205 + + self.conf[key] = value 206 + 207 + 208 + def load(): 209 + - return GconfDict() 210 + + return ConfigFile() 211 + 212 + 213 + def save(data): 214 + @@ -208,25 +138,4 @@ def get(descriptor): 215 + value = get(prefs.SUPPORT_DIRECTORY) 216 + value = os.path.join(value, 'miro-helper.log') 217 + 218 + - elif descriptor == prefs.HTTP_PROXY_ACTIVE: 219 + - return _get_gconf("/system/http_proxy/use_http_proxy") 220 + - 221 + - elif descriptor == prefs.HTTP_PROXY_HOST: 222 + - return _get_gconf("/system/http_proxy/host") 223 + - 224 + - elif descriptor == prefs.HTTP_PROXY_PORT: 225 + - return _get_gconf("/system/http_proxy/port") 226 + - 227 + - elif descriptor == prefs.HTTP_PROXY_AUTHORIZATION_ACTIVE: 228 + - return _get_gconf("/system/http_proxy/use_authentication") 229 + - 230 + - elif descriptor == prefs.HTTP_PROXY_AUTHORIZATION_USERNAME: 231 + - return _get_gconf("/system/http_proxy/authentication_user") 232 + - 233 + - elif descriptor == prefs.HTTP_PROXY_AUTHORIZATION_PASSWORD: 234 + - return _get_gconf("/system/http_proxy/authentication_password") 235 + - 236 + - elif descriptor == prefs.HTTP_PROXY_IGNORE_HOSTS: 237 + - return _get_gconf("/system/http_proxy/ignore_hosts", []) 238 + - 239 + return value 240 + diff --git a/plat/frontends/widgets/application.py b/plat/frontends/widgets/application.py 241 + index a1eaaf3..20f4c23 100644 242 + --- a/plat/frontends/widgets/application.py 243 + +++ b/plat/frontends/widgets/application.py 244 + @@ -35,7 +35,6 @@ except RuntimeError: 245 + sys.exit(1) 246 + import gobject 247 + import os 248 + -import gconf 249 + import shutil 250 + import platform 251 + 252 + @@ -53,7 +52,6 @@ from miro import prefs 253 + from miro.frontends.widgets.application import Application 254 + # from miro.plat.frontends.widgets import threads 255 + from miro.plat import renderers, options 256 + -from miro.plat.config import gconf_lock, gconf_key 257 + try: 258 + from miro.plat.frontends.widgets import miroappindicator 259 + APP_INDICATOR_SUPPORT = True 260 + @@ -77,29 +75,13 @@ import sys 261 + 262 + 263 + def _get_pref(key, getter_name): 264 + - gconf_lock.acquire() 265 + - try: 266 + - client = gconf.client_get_default() 267 + - fullkey = gconf_key(key) 268 + - value = client.get(fullkey) 269 + - if value is not None: 270 + - getter = getattr(value, getter_name) 271 + - return getter() 272 + - else: 273 + - return None 274 + - finally: 275 + - gconf_lock.release() 276 + + # XXX: ugly! 277 + + return app.config._data.get(key) 278 + 279 + 280 + def _set_pref(key, setter_name, value): 281 + - gconf_lock.acquire() 282 + - try: 283 + - client = gconf.client_get_default() 284 + - fullkey = gconf_key(key) 285 + - setter = getattr(client, setter_name) 286 + - setter(fullkey, value) 287 + - finally: 288 + - gconf_lock.release() 289 + + # XXX: ugly! 290 + + app.config._data[key] = value 291 + 292 + 293 + def get_int(key): 294 + diff --git a/plat/options.py b/plat/options.py 295 + index 4ea1a67..8e75e20 100644 296 + --- a/plat/options.py 297 + +++ b/plat/options.py 298 + @@ -69,14 +69,14 @@ USE_RENDERER = LinuxPref( 299 + 300 + GSTREAMER_IMAGESINK = LinuxPref( 301 + key="DefaultGstreamerImagesink", 302 + - default="gconfvideosink", 303 + + default="autovideosink", 304 + alias="gstreamer-imagesink", 305 + helptext=("Which GStreamer image sink to use for video. " 306 + "(autovideosink, ximagesink, xvimagesink, gconfvideosink, ...)")) 307 + 308 + GSTREAMER_AUDIOSINK = LinuxPref( 309 + key="DefaultGstreamerAudiosink", 310 + - default="gconfaudiosink", 311 + + default="autoaudiosink", 312 + alias="gstreamer-audiosink", 313 + helptext=("Which GStreamer sink to use for audio. " 314 + "(autoaudiosink, osssink, alsasink, gconfaudiosink, ...)")) 315 + diff --git a/plat/upgrade.py b/plat/upgrade.py 316 + index 9677e3a..f812ad4 100644 317 + --- a/plat/upgrade.py 318 + +++ b/plat/upgrade.py 319 + @@ -30,7 +30,6 @@ 320 + import os 321 + import shutil 322 + from miro.plat import resources 323 + -import gconf 324 + 325 + 326 + def upgrade(): 327 + @@ -64,47 +63,3 @@ def upgrade(): 328 + os.remove(old_file) 329 + except OSError: 330 + pass 331 + - 332 + - # gconf settings 333 + - client = gconf.client_get_default() 334 + - 335 + - def _copy_gconf(src, dst): 336 + - for entry in client.all_entries(src): 337 + - entry_dst = dst + '/' + entry.key.split('/')[-1] 338 + - client.set(entry_dst, entry.value) 339 + - for subdir in client.all_dirs(src): 340 + - subdir_dst = dst + '/' + subdir.split('/')[-1] 341 + - _copy_gconf(subdir, subdir_dst) 342 + - 343 + - if ((client.dir_exists("/apps/democracy/player") 344 + - and not client.dir_exists("/apps/miro"))): 345 + - _copy_gconf("/apps/democracy/player", "/apps/miro") 346 + - client.recursive_unset("/apps/democracy", 1) 347 + - 348 + - # Set the MoviesDirectory and NonVideoDirectory based on the 349 + - # possibilities that we've had over the years and what exists on 350 + - # the user's system. This codifies it in the user's gconf so that 351 + - # when we change it in future, then the user isn't affected. 352 + - from miro.plat import options 353 + - if options.gconf_name is None: 354 + - options.gconf_name = "miro" 355 + - key = "/apps/%s/MoviesDirectory" % options.gconf_name 356 + - if client.get(key) is None: 357 + - for mem in ["~/.miro/Movies", # packages 358 + - "~/Videos/Miro", 359 + - "~/Movies/Miro", # pre 3.5 360 + - "~/Movies/Democracy" # democracy player 361 + - ]: 362 + - mem = os.path.expanduser(mem) 363 + - if os.path.exists(mem): 364 + - client.set_string(key, mem) 365 + - break 366 + - 367 + - key = "/apps/%s/NonVideoDirectory" % options.gconf_name 368 + - if client.get(key) is None: 369 + - for mem in ["~/.miro/Nonvideo" # packages 370 + - ]: 371 + - mem = os.path.expanduser(mem) 372 + - if os.path.exists(mem): 373 + - client.set_string(key, mem) 374 + - break
+4
pkgs/top-level/all-packages.nix
··· 5210 5210 5211 5211 minmay = callPackage ../development/libraries/minmay { }; 5212 5212 5213 + miro = callPackage ../applications/video/miro { 5214 + inherit (pythonPackages) pywebkitgtk pysqlite pycurl mutagen; 5215 + }; 5216 + 5213 5217 mkvtoolnix = callPackage ../applications/video/mkvtoolnix { }; 5214 5218 5215 5219 mlt = callPackage ../development/libraries/mlt {